diff --git a/INSTALL b/INSTALL index 632a6cb6bf..52b2a8e118 100644 --- a/INSTALL +++ b/INSTALL @@ -157,10 +157,12 @@ sudo apk add alpine-sdk lmdb-dev openssl-dev bison flex-dev acl-dev pcre2-dev au Note that in order for process promises to work you must install the procps package for a "proper" ps command instead of busybox. -* Termux (2020-04-24) +* Termux (2025-10-10) -pkg install build-essential git autoconf automake bison flex liblmdb openssl pcre2 libacl libyaml -./autogen.sh --without-pam +pkg install build-essential git autoconf automake bison flex liblmdb openssl pcre2 libacl libyaml binutils librsync +# maybe binutils-is-llvm - Use llvm as binutils instead of binutils to get ld +LDFLAGS='-landroid-glob' ./autogen.sh --without-pam --prefix=$PREFIX --with-workdir=$PREFIX/var/lib/cfengine --without-systemd-service --without-selinux-policy +make && make install * OSX (2021-10-20) diff --git a/configure.ac b/configure.ac index ae69ca1444..165976b222 100644 --- a/configure.ac +++ b/configure.ac @@ -181,6 +181,14 @@ CC="$PTHREAD_CC" CFLAGS="$PTHREAD_CFLAGS $CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" +dnl ###################################################################### +dnl libpromises/evalfunction.c isreadable() uses pthread_cancel so check +dnl if available and reverts to pthread_kill if not. +dnl This check must come after ACX_PTHREAD is called so that CC, CFLAGS, +dnl and LIBS are appropriately set for the local pthreads situation. +dnl ###################################################################### +AC_CHECK_FUNCS([pthread_cancel]) + dnl ###################################################################### dnl Whether to build extensions as builtin extensions or a separate dnl plugin. The default is plugin. @@ -1341,7 +1349,7 @@ AC_CHECK_DECLS([FALLOC_FL_PUNCH_HOLE], [], [], [ ]) AC_CHECK_HEADERS([sys/sendfile.h]) AC_CHECK_FUNCS([sendfile]) -AC_CHECK_FUNCS([copy_file_range]) +AC_CHECK_DECL([copy_file_range]) dnl ####################################################################### diff --git a/i b/i new file mode 100755 index 0000000000..2e3c62eb8f --- /dev/null +++ b/i @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +set -ex +export LDFLAGS+=" -landroid-glob" +./autogen.sh \ + --prefix=$PREFIX \ + --with-workdir=$PREFIX/var/lib/cfengine \ + --without-pam \ + --without-selinux-policy \ + --without-systemd-service +make -j8 install +#DESTDIR=/data/data/com.termux/files make -j8 install diff --git a/libenv/sysinfo.c b/libenv/sysinfo.c index b72f5de1d1..a41f144633 100644 --- a/libenv/sysinfo.c +++ b/libenv/sysinfo.c @@ -3809,6 +3809,12 @@ static void SysOSNameHuman(EvalContext *ctx) "Alpine", CF_DATA_TYPE_STRING, "source=agent,derived-from=alpine"); } + else if (EvalContextClassGet(ctx, NULL, "termux") != NULL) + { + EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, lval, + "Termux", CF_DATA_TYPE_STRING, + "source=agent,derived-from=termux"); + } else if (EvalContextClassGet(ctx, NULL, "gentoo") != NULL) { EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, lval, diff --git a/libpromises/dbm_test_api.c b/libpromises/dbm_test_api.c index def4d50b92..2d8f3d4007 100644 --- a/libpromises/dbm_test_api.c +++ b/libpromises/dbm_test_api.c @@ -22,6 +22,7 @@ included file COSL.txt. */ +#ifndef __ANDROID__ #include #include /* lrand48_r() */ #include /* usleep(), syscall()/gettid() */ @@ -735,3 +736,4 @@ void RemoveFilament(DBFilament *filament) free(filament); CloseDB(db); } +#endif /* not __ANDROID__ */ diff --git a/libpromises/dbm_test_api.h b/libpromises/dbm_test_api.h index ffda177d75..a6fe0ae63d 100644 --- a/libpromises/dbm_test_api.h +++ b/libpromises/dbm_test_api.h @@ -22,6 +22,7 @@ included file COSL.txt. */ +#ifndef __ANDROID__ #ifndef CFENGINE_DBM_TEST_API_H #define CFENGINE_DBM_TEST_API_H @@ -55,3 +56,4 @@ DBFilament *FillUpDB(dbid db_id, int usage_pct); void RemoveFilament(DBFilament *filament); #endif /* CFENGINE_DBM_TEST_API_H */ +#endif /* not __ANDROID__ */ diff --git a/libpromises/evalfunction.c b/libpromises/evalfunction.c index 2889cc6bef..52fadc65da 100644 --- a/libpromises/evalfunction.c +++ b/libpromises/evalfunction.c @@ -86,6 +86,7 @@ #include #include /* ThreadWait */ #include +#include /* MaskTerminationSignalsInThread */ #include @@ -9672,10 +9673,29 @@ struct IsReadableThreadData bool success; }; +#ifndef HAVE_PTHREAD_CANCEL +#define PTHREAD_CANCELED ((void *)-1) +static void ThreadSignalHandler(int signum) +{ + pthread_exit(PTHREAD_CANCELED); +} +#endif + static void *IsReadableThreadRoutine(void *data) { assert(data != NULL); +#ifndef HAVE_PTHREAD_CANCEL + MaskTerminationSignalsInThread(); + struct sigaction actions; + memset(&actions, 0, sizeof(actions)); + sigemptyset(&actions.sa_mask); + actions.sa_flags = 0; + actions.sa_handler = ThreadSignalHandler; + sigaction(SIGHUP, &actions, NULL); + MaskTerminationSignalsInThread(); +#endif + struct IsReadableThreadData *const thread_data = data; // Give main thread time to call pthread_cond_timedwait(3) @@ -9827,7 +9847,11 @@ static FnCallResult FnCallIsReadable(ARG_UNUSED EvalContext *const ctx, "Read operation timed out, exceeded %ld seconds.", path, timeout); +#ifdef HAVE_PTHREAD_CANCEL ret = pthread_cancel(thread_data.thread); +#else + ret = pthread_kill(thread_data.thread, SIGUSR2); +#endif if (ret != 0) { Log(LOG_LEVEL_ERR, "Failed to cancel thread"); @@ -9857,10 +9881,12 @@ static FnCallResult FnCallIsReadable(ARG_UNUSED EvalContext *const ctx, return FnFailure(); } +#ifdef HAVE_PTHREAD_CANCEL if (status == PTHREAD_CANCELED) { Log(LOG_LEVEL_DEBUG, "Thread was canceled"); } +#endif return FnReturnContext(success); } diff --git a/libpromises/generic_agent.c b/libpromises/generic_agent.c index 1e67f53f8d..ee516502d5 100644 --- a/libpromises/generic_agent.c +++ b/libpromises/generic_agent.c @@ -2476,6 +2476,17 @@ bool GenericAgentConfigParseArguments(GenericAgentConfig *config, int argc, char if (argc > 1) { +Log(LOG_LEVEL_ERR, "Special 1-arg expected, got %d arguments instead. See debug output for details.", argc); +for (int i=0; i= 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. + +See INSTALL DEPENDENCIES below for example of deps for various systems. + +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://groups.google.com/forum/#!forum/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, laid 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. + +INSTALL DEPENDENCIES +-------------------- + +Here we have examples of command lines for various systems to install dependencies +needed to build. The version and date checked are noted in parenthesis. Please +submit PRs with updates to this information. + +* RedHat/CentOS (rhel-8/rhel-9/centos-7 2022-11-15) + +Note that first you will need to install epel-release (https://fedoraproject.org/wiki/EPEL) for lmdb-devel to be available. + +$ sudo yum install -y gcc gdb make git libtool autoconf automake byacc flex openssl-devel pcre-devel lmdb-devel pam-devel flex-devel libyaml-devel + +For SELinux support you will need selinux-policy-devel package and specify `--with-selinux-policy` to `autogen.sh` or `configure` + +* Debian (Raspbian 10 2021-07-02) + +$ sudo apt-get install -y build-essential git libtool autoconf automake bison flex libssl-dev libpcre3-dev libbison-dev libacl1 libacl1-dev lmdb-utils liblmdb-dev libpam0g-dev libtool libyaml-dev + +* FreeBSD (12.1 2020-04-07) + +See docs/BSD.md + +* SUSE (Tumbleweed 2020-02-02) + +$ sudo zypper install gdb gcc make lmdb autoconf automake libtool git python3 pcre-devel libopenssl-devel pam-devel + +* AlpineOS (3.11.3 x86_64 2020-04-13) + +$ sudo apk add alpine-sdk lmdb-dev openssl-dev bison flex-dev acl-dev pcre-dev autoconf automake libtool git python3 gdb +$ ./autogen.sh --without-pam + +* Termux (2020-04-24) + +pkg install -y build-essential git autoconf automake bison flex liblmdb openssl pcre libacl libyaml +# ld is not found with clang (from build-essential?) so add binutils +# also need rsync +./autogen.sh --without-pam + +* OSX (2021-10-20) + +brew install openssl@1.1 lmdb autoconf automake libtool bison flex pcre m4 gcc make +./autogen.sh --enable-debug --with-openssl="$(brew --prefix openssl@1.1)" diff --git a/tests/acceptance/testall b/tests/acceptance/testall index adc73a6c9d..693974822c 100755 --- a/tests/acceptance/testall +++ b/tests/acceptance/testall @@ -285,9 +285,9 @@ workdir() { } # Example: fgrepvar 'word' VARNAME -# Silent fgrep for variables: search for "word" in $VARNAME -fgrepvar() { - eval echo \$$2 | fgrep "$1" > /dev/null +# Silent grep -F for variables: search for "word" in $VARNAME +fgrepvar(){ + eval echo \$$2 | grep -F "$1" > /dev/null } # Same but instead of word search for a regex @@ -519,22 +519,22 @@ export CFENGINE_TEST_OVERRIDE_WORKDIR TEMP CFENGINE_TEST_OVERRIDE_EXTENSION_LIBR echo "Return code is $RETVAL." >> "$WORKDIR/$LOG" # Try to collect test metadata if any - if egrep "R: test description: " $OUTFILE > /dev/null + if grep -E "R: test description: " $OUTFILE > /dev/null then - TEST_DESCRIPTION="$(egrep "R: test description" $OUTFILE | sed -e "s,.*test description: \([A-Za-z0-9_]*\),\1,")" + TEST_DESCRIPTION="$(grep -E "R: test description" $OUTFILE | sed -e "s,.*test description: \([A-Za-z0-9_]*\),\1,")" fi - if egrep -e "R: test story_id: " $OUTFILE > /dev/null + if grep -E -e "R: test story_id: " $OUTFILE > /dev/null then - TEST_STORY="$(egrep "R: test story_id" $OUTFILE | sed -e "s,.*test story_id: \([0-9][0-9]*\),\1,")" + TEST_STORY="$(grep -E "R: test story_id" $OUTFILE | sed -e "s,.*test story_id: \([0-9][0-9]*\),\1,")" fi - if egrep -e "R: test covers: " $OUTFILE > /dev/null + if grep -E -e "R: test covers: " $OUTFILE > /dev/null then - TEST_COVERS="$(egrep "R: test covers" $OUTFILE | sed -e "s,.*test covers: \([A-Za-z0-9_]*\),\1,")" + TEST_COVERS="$(grep -E "R: test covers" $OUTFILE | sed -e "s,.*test covers: \([A-Za-z0-9_]*\),\1,")" fi if [ $TEST_TYPE = errorexit ] then - if [ $RETVAL -gt 0 ] && [ $RETVAL -lt 128 ] && egrep "error:|aborted on defined class" $OUTFILE > /dev/null + if [ $RETVAL -gt 0 ] && [ $RETVAL -lt 128 ] && grep -E "error:|aborted on defined class" $OUTFILE > /dev/null then RESULT=Pass RESULT_MSG="${COLOR_SUCCESS}Pass${COLOR_NORMAL}" @@ -552,7 +552,7 @@ export CFENGINE_TEST_OVERRIDE_WORKDIR TEMP CFENGINE_TEST_OVERRIDE_EXTENSION_LIBR then RESULT=FAIL RESULT_MSG="${COLOR_FAILURE}FAIL (NON-ZERO EXIT CODE!)${COLOR_NORMAL}" - elif fgrep 'error: ' "$OUTFILE" > /dev/null + elif grep -F 'error: ' "$OUTFILE" > /dev/null then RESULT=Pass RESULT_MSG="${COLOR_SUCCESS}Pass${COLOR_NORMAL}" @@ -570,21 +570,21 @@ export CFENGINE_TEST_OVERRIDE_WORKDIR TEMP CFENGINE_TEST_OVERRIDE_EXTENSION_LIBR # 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 "R: .*$ESCAPED_TEST [XS]FAIL" $OUTFILE > /dev/null && ! egrep "R: .*$ESCAPED_TEST Wait/" $OUTFILE > /dev/null + if grep -E "R: .*$ESCAPED_TEST [XS]FAIL" $OUTFILE > /dev/null && ! grep -E "R: .*$ESCAPED_TEST Wait/" $OUTFILE > /dev/null then # Check for passed outcome, which should not happen. - if egrep "R: .*$ESCAPED_TEST " $OUTFILE | egrep "R: .*$ESCAPED_TEST Pass" > /dev/null + if grep -E "R: .*$ESCAPED_TEST " $OUTFILE | grep -E "R: .*$ESCAPED_TEST Pass" > /dev/null then RESULT=FAIL RESULT_MSG="${COLOR_FAILURE}FAIL (The test Passed, but failure was expected)${COLOR_NORMAL}" - elif egrep "R: .*$ESCAPED_TEST " $OUTFILE | egrep -v "R: .*$ESCAPED_TEST [XS]?FAIL" > /dev/null + elif grep -E "R: .*$ESCAPED_TEST " $OUTFILE | grep -E -v "R: .*$ESCAPED_TEST [XS]?FAIL" > /dev/null then # Other test case outcomes than fail. Should not happen. RESULT=FAIL RESULT_MSG="${COLOR_FAILURE}FAIL (Failure was expected, but the test had an unexpected test outcome, check test output, Pass/FAIL need to match exactly)${COLOR_NORMAL}" else - TICKET="$(egrep "R: .*$ESCAPED_TEST [XS]FAIL" $OUTFILE | sed -e "s,.*[XS]FAIL/\(.*\),\1,")" - RESULT="$(egrep "R: .*$ESCAPED_TEST [XS]FAIL" $OUTFILE | sed -e "s,.*\([XS]FAIL\).*,\1,")" + TICKET="$(grep -E "R: .*$ESCAPED_TEST [XS]FAIL" $OUTFILE | sed -e "s,.*[XS]FAIL/\(.*\),\1,")" + RESULT="$(grep -E "R: .*$ESCAPED_TEST [XS]FAIL" $OUTFILE | sed -e "s,.*\([XS]FAIL\).*,\1,")" if [ "$RESULT" = "XFAIL" ] then RESULT_MSG="${COLOR_WARNING}FAIL (Suppressed, $TICKET)${COLOR_NORMAL}" @@ -595,38 +595,38 @@ export CFENGINE_TEST_OVERRIDE_WORKDIR TEMP CFENGINE_TEST_OVERRIDE_EXTENSION_LIBR elif [ $RETVAL -ne 0 ] then RESULT=FAIL - elif egrep "R: .*$ESCAPED_TEST FAIL/no_ticket_number" $OUTFILE > /dev/null + elif grep -E "R: .*$ESCAPED_TEST FAIL/no_ticket_number" $OUTFILE > /dev/null then RESULT=FAIL RESULT_MSG="${COLOR_FAILURE}FAIL (Tried to suppress failure, but no issue number is provided)${COLOR_NORMAL}" - elif egrep "R: .*$ESCAPED_TEST Wait/[0-9]+" $OUTFILE > /dev/null + elif grep -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 "R: .*$ESCAPED_TEST Wait/[0-9]+" $OUTFILE | sed -e 's,.*Wait/\([0-9][0-9]*\).*,\1,') + WAIT_TIME=$(grep -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 "R: .*$ESCAPED_TEST Pass" $OUTFILE > /dev/null + elif grep -E "R: .*$ESCAPED_TEST Pass" $OUTFILE > /dev/null then RESULT=Pass RESULT_MSG="${COLOR_SUCCESS}Pass${COLOR_NORMAL}" - elif egrep "R: .*$ESCAPED_TEST Skip/unsupported" $OUTFILE > /dev/null + elif grep -E "R: .*$ESCAPED_TEST Skip/unsupported" $OUTFILE > /dev/null then RESULT=Skip RESULT_MSG="${COLOR_WARNING}Skipped (No platform support)${COLOR_NORMAL}" - elif egrep "R: .*$ESCAPED_TEST Skip/needs_work" $OUTFILE > /dev/null + elif grep -E "R: .*$ESCAPED_TEST Skip/needs_work" $OUTFILE > /dev/null then RESULT=Skip RESULT_MSG="${COLOR_WARNING}Skipped (Test needs work)${COLOR_NORMAL}" - elif egrep "R: .*$ESCAPED_TEST FLAKEY" $OUTFILE > /dev/null + elif grep -E "R: .*$ESCAPED_TEST FLAKEY" $OUTFILE > /dev/null then RESULT=FLAKEY - TICKET="$(egrep "R: .*$ESCAPED_TEST FLAKEY" $OUTFILE | sed -e "s,.*FLAKEY/\(.*\),\1,")" + TICKET="$(grep -E "R: .*$ESCAPED_TEST FLAKEY" $OUTFILE | sed -e "s,.*FLAKEY/\(.*\),\1,")" RESULT_MSG="${COLOR_WARNING}Flakey fail ($TICKET)${COLOR_NORMAL}" else @@ -1070,7 +1070,7 @@ fi for addtest in $ALL_TESTS do - if echo "$addtest" | fgrep "/timed/" > /dev/null + if echo "$addtest" | grep -F "/timed/" > /dev/null then if [ "$TIMED_TESTS" = 1 ] then @@ -1128,12 +1128,12 @@ print_header() { print_footer() { # Recalculate results since sub invocations may not have been recorded. - PASSED_TESTS=`egrep '^Pass ' $SUMMARY | wc -l | tr -d ' '` - FAILED_TESTS=`egrep '^(FAIL|XFAIL) ' $SUMMARY | wc -l | tr -d ' '` - SUPPRESSED_FAILURES=`egrep '^XFAIL ' $SUMMARY | wc -l | tr -d ' '` - SOFT_FAILURES=`egrep '^SFAIL ' $SUMMARY | wc -l | tr -d ' '` - FLAKEY_FAILURES=`egrep '^FLAKEY ' $SUMMARY | wc -l | tr -d ' '` - SKIPPED_TESTS=`egrep '^Skip ' $SUMMARY | wc -l | tr -d ' '` + PASSED_TESTS=`grep -E '^Pass ' $SUMMARY | wc -l | tr -d ' '` + FAILED_TESTS=`grep -E '^(FAIL|XFAIL) ' $SUMMARY | wc -l | tr -d ' '` + SUPPRESSED_FAILURES=`grep -E '^XFAIL ' $SUMMARY | wc -l | tr -d ' '` + SOFT_FAILURES=`grep -E '^SFAIL ' $SUMMARY | wc -l | tr -d ' '` + FLAKEY_FAILURES=`grep -E '^FLAKEY ' $SUMMARY | wc -l | tr -d ' '` + SKIPPED_TESTS=`grep -E '^Skip ' $SUMMARY | wc -l | tr -d ' '` ( echo echo ======================================================================