diff --git a/.gitignore b/.gitignore index dd3d6db83cf..29abcb42046 100644 --- a/.gitignore +++ b/.gitignore @@ -74,6 +74,8 @@ src/client/linking.sexp src/core/developer src/manifest/dune src/manifest/install.inc +src/stubs/libacl/dune +src/stubs/libacl/c-libraries.sexp src/stubs/win32/cc64 src/stubs/win32/dune src/stubs/c-flags.sexp diff --git a/Makefile b/Makefile index 74b2519cd1d..ae90175d6e1 100644 --- a/Makefile +++ b/Makefile @@ -79,7 +79,7 @@ clean: distclean: clean clean-ext rm -rf autom4te.cache bootstrap rm -f Makefile.config config.log config.status aclocal.m4 - rm -f src/*.META src/*/.merlin src/manifest/dune src/manifest/install.inc src/stubs/win32/dune src/stubs/win32/cc64 src/ocaml-flags-configure.sexp + rm -f src/*.META src/*/.merlin src/manifest/dune src/manifest/install.inc src/stubs/libacl/dune src/stubs/win32/dune src/stubs/win32/cc64 src/ocaml-flags-configure.sexp src/stubs/libacl/c-libraries.sexp rm -f src/client/linking.sexp src/stubs/c-flags.sexp src/core/developer src/core/version OPAMINSTALLER_FLAGS = --prefix "$(DESTDIR)$(prefix)" diff --git a/configure b/configure index 069a62750b0..00da9d15f10 100755 --- a/configure +++ b/configure @@ -197,7 +197,8 @@ 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 \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else @@ -584,6 +585,42 @@ PACKAGE_BUGREPORT='' PACKAGE_URL='' ac_default_prefix=`echo "os_type: ${OCAML_OS_TYPE}" | sed -e "s;^os_type: Win32;C:/OPAM;" -e "s;^os_type:.*;/usr/local;"` +# 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_subst_vars='LTLIBOBJS LIBOBJS hasalldeps @@ -620,6 +657,10 @@ PATH_PREPEND CC64 CONF_CFLAGS CONF_OCAMLFLAGS +CONF_LIBACL_LINK +EGREP +GREP +CPP MCCS_ENABLED DEVELOPER OBJEXT @@ -698,6 +739,7 @@ enable_version_check enable_checks enable_developer_mode with_mccs +with_libacl with_private_runtime enable_cold_check enable_certificate_check @@ -710,6 +752,7 @@ CFLAGS LDFLAGS LIBS CPPFLAGS +CPP CXX CXXFLAGS CCC' @@ -1349,6 +1392,7 @@ Optional Packages: --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --without-mccs Compile without a built-in Cudf solver (only works if 'mccs' is not otherwise installed) + --with-libacl Compile opam with libacl support --with-private-runtime For a mingw-w64 build, manifest the runtime DLLs locally in Opam.Runtime.arch @@ -1360,6 +1404,7 @@ Some influential environment variables: 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 CXX C++ compiler command CXXFLAGS C++ compiler flags @@ -1483,6 +1528,249 @@ fi } # 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_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_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_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_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_cxx_try_compile LINENO # ---------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. @@ -3160,6 +3448,15 @@ fi +# Check whether --with-libacl was given. +if test "${with_libacl+set}" = set; then : + withval=$with_libacl; +else + with_libacl=auto +fi + + + # Check whether --with-private_runtime was given. if test "${with_private_runtime+set}" = set; then : withval=$with_private_runtime; @@ -3978,6 +4275,502 @@ else 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 +{ $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 + + +{ $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 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 + + +if test "x${with_libacl}" != "xno"; then : + + have_libacl=yes + ac_fn_c_check_header_mongrel "$LINENO" "acl/libacl.h" "ac_cv_header_acl_libacl_h" "$ac_includes_default" +if test "x$ac_cv_header_acl_libacl_h" = xyes; then : + +else + have_libacl=no +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing acl_get_perm" >&5 +$as_echo_n "checking for library containing acl_get_perm... " >&6; } +if ${ac_cv_search_acl_get_perm+:} 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 acl_get_perm (); +int +main () +{ +return acl_get_perm (); + ; + return 0; +} +_ACEOF +for ac_lib in '' acl; 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_acl_get_perm=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_acl_get_perm+:} false; then : + break +fi +done +if ${ac_cv_search_acl_get_perm+:} false; then : + +else + ac_cv_search_acl_get_perm=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_acl_get_perm" >&5 +$as_echo "$ac_cv_search_acl_get_perm" >&6; } +ac_res=$ac_cv_search_acl_get_perm +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +else + have_libacl=no +fi + + if test "x${SYSTEM}" = "xcygwin"; then : + + if test "x${have_libacl}" = "xno"; then : + as_fn_error $? "opam on Cygwin requires libacl" "$LINENO" 5 +else + with_libacl=yes +fi + +fi + if test "x${with_libacl}${have_libacl}" = "xyesno"; then : + as_fn_error $? "libacl not found" "$LINENO" 5 +fi + +fi +if test "x${with_libacl}" = "xyes"; then : + + if test "x${ac_cv_search_acl_get_perm}" = "xnone required"; then : + + + +else + + CONF_LIBACL_LINK=${ac_cv_search_acl_get_perm} + + +fi + +fi + CONF_OCAMLFLAGS="-w -67" if test "x${CI}" != "x"; then : @@ -5511,7 +6304,7 @@ if test "x$prefix" = "xNONE"; then prefix=$ac_default_prefix fi -ac_config_files="$ac_config_files Makefile.config src/ocaml-flags-configure.sexp src/stubs/c-flags.sexp" +ac_config_files="$ac_config_files Makefile.config src/ocaml-flags-configure.sexp src/stubs/c-flags.sexp src/stubs/libacl/c-libraries.sexp" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -6222,6 +7015,7 @@ do "Makefile.config") CONFIG_FILES="$CONFIG_FILES Makefile.config" ;; "src/ocaml-flags-configure.sexp") CONFIG_FILES="$CONFIG_FILES src/ocaml-flags-configure.sexp" ;; "src/stubs/c-flags.sexp") CONFIG_FILES="$CONFIG_FILES src/stubs/c-flags.sexp" ;; + "src/stubs/libacl/c-libraries.sexp") CONFIG_FILES="$CONFIG_FILES src/stubs/libacl/c-libraries.sexp" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac @@ -6698,6 +7492,14 @@ if test ${WIN32} -eq 1; then : ${LN_S} -f dune-win32 dune cd ../../.. +fi +rm -f src/stubs/libacl/dune +if test "x${with_libacl}" = "xyes" ; then : + + cd src/stubs/libacl + ${LN_S} -f dune-libacl dune + cd ../../.. + fi echo diff --git a/configure.ac b/configure.ac index 41e8c18a206..691a7b8deca 100644 --- a/configure.ac +++ b/configure.ac @@ -55,6 +55,10 @@ AC_ARG_WITH([mccs], [Compile without a built-in Cudf solver (only works if 'mccs' is not otherwise installed)]),[],[MCCS_DEFAULT=yes] ) +AC_ARG_WITH([libacl], + AC_HELP_STRING([--with-libacl], + [Compile opam with libacl support]),,[with_libacl=auto]) + AC_ARG_WITH([private_runtime], AC_HELP_STRING([--with-private-runtime], [For a mingw-w64 build, manifest the runtime DLLs locally in Opam.Runtime.arch]),,[with_private_runtime=no] @@ -138,6 +142,23 @@ AS_IF([test "x${enable_developer_mode}" = "xyes"],[ AS_IF([test "x${with_mccs}" = "xno"], [AC_SUBST(MCCS_ENABLED,false)], [AC_SUBST(MCCS_ENABLED,true)]) +AS_IF([test "x${with_libacl}" != "xno"],[ + have_libacl=yes + AC_CHECK_HEADER([acl/libacl.h],,[have_libacl=no]) + AC_SEARCH_LIBS([acl_get_perm],[acl],,[have_libacl=no]) + AS_IF([test "x${SYSTEM}" = "xcygwin"],[ + AS_IF([test "x${have_libacl}" = "xno"],[AC_MSG_ERROR([opam on Cygwin requires libacl])],[with_libacl=yes]) + ]) + AS_IF([test "x${with_libacl}${have_libacl}" = "xyesno"],[AC_MSG_ERROR([libacl not found])]) +]) +AS_IF([test "x${with_libacl}" = "xyes"],[ + AS_IF([test "x${ac_cv_search_acl_get_perm}" = "xnone required"],[ + AC_SUBST(CONF_LIBACL_LINK,[]) + ],[ + AC_SUBST(CONF_LIBACL_LINK,[${ac_cv_search_acl_get_perm}]) + ]) +]) + CONF_OCAMLFLAGS="-w -67" AS_IF([test "x${CI}" != "x"], [ @@ -358,6 +379,7 @@ AC_CONFIG_FILES( Makefile.config src/ocaml-flags-configure.sexp src/stubs/c-flags.sexp + src/stubs/libacl/c-libraries.sexp ) AC_OUTPUT @@ -379,6 +401,12 @@ AS_IF([ test ${WIN32} -eq 1],[ ${LN_S} -f dune-win32 dune cd ../../.. ]) +rm -f src/stubs/libacl/dune +AS_IF([ test "x${with_libacl}" = "xyes" ],[ + cd src/stubs/libacl + ${LN_S} -f dune-libacl dune + cd ../../.. +]) echo diff --git a/src/core/dune b/src/core/dune index 44e6e46252d..a0a060f49ba 100644 --- a/src/core/dune +++ b/src/core/dune @@ -3,6 +3,9 @@ (public_name opam-core) (synopsis "OCaml Package Manager core internal stdlib") (libraries re ocamlgraph unix bigarray + (select opamACL.ml from + (opam-core.libacl -> opamACL.ml.libacl) + ( -> opamACL.ml.dummy)) (select opamStubs.ml from (opam-core.stubs -> opamStubs.ml.win32) ( -> opamStubs.ml.dummy))) diff --git a/src/core/opamACL.ml.dummy b/src/core/opamACL.ml.dummy new file mode 100644 index 00000000000..7d780f43da0 --- /dev/null +++ b/src/core/opamACL.ml.dummy @@ -0,0 +1,11 @@ +(**************************************************************************) +(* *) +(* Copyright 2020 David Allsopp Ltd. *) +(* *) +(* All rights reserved. This file is distributed under the terms of the *) +(* GNU Lesser General Public License version 2.1, with the special *) +(* exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +let get_acl_executable_info _ _ = None diff --git a/src/core/opamACL.ml.libacl b/src/core/opamACL.ml.libacl new file mode 100644 index 00000000000..4cc599b5efc --- /dev/null +++ b/src/core/opamACL.ml.libacl @@ -0,0 +1,11 @@ +(**************************************************************************) +(* *) +(* Copyright 2020 David Allsopp Ltd. *) +(* *) +(* All rights reserved. This file is distributed under the terms of the *) +(* GNU Lesser General Public License version 2.1, with the special *) +(* exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +include OpamlibACL diff --git a/src/core/opamACL.mli b/src/core/opamACL.mli new file mode 100644 index 00000000000..4fb451be994 --- /dev/null +++ b/src/core/opamACL.mli @@ -0,0 +1,22 @@ +(**************************************************************************) +(* *) +(* Copyright 2020 David Allsopp Ltd. *) +(* *) +(* All rights reserved. This file is distributed under the terms of the *) +(* GNU Lesser General Public License version 2.1, with the special *) +(* exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +(** C auxiliary function used for POSIX 1003.1e DRAFT 17 permission checking. *) + +val get_acl_executable_info : string -> int -> int list option + (** If compiled without libacl support, this function always returns None + When opam is built with libacl support, + [get_acl_executable_info file owner] takes a filename and the uid of the + owner of that file (this is passed since the caller will have already + called {!Unix.stat}). The function returns [Some []] if the process can + execute [file] or [Some gids] if the process can execute [file] if one + of its groups matches [gids]. If the process cannot under any + circumstances execute [file] (or if an unexpected error occurred), then + [None] is returned. *) diff --git a/src/core/opamSystem.ml b/src/core/opamSystem.ml index 5f924b6ea74..1bf1776f4a4 100644 --- a/src/core/opamSystem.ml +++ b/src/core/opamSystem.ml @@ -386,17 +386,24 @@ let t_resolve_command = else fun f -> try let open Unix in - let uid = geteuid() and groups = getegid() :: Array.to_list(getgroups()) in + let uid = geteuid () in + let groups = OpamStd.IntSet.of_list (getegid () :: Array.to_list (getgroups ())) in let {st_uid; st_gid; st_perm; _} = stat f in let mask = if uid = st_uid then 0o100 - else if List.mem st_gid groups then + else if OpamStd.IntSet.mem st_gid groups then 0o010 else 0o001 in - (st_perm land mask) <> 0 + if (st_perm land mask) <> 0 then + true + else + match OpamACL.get_acl_executable_info f st_uid with + | None -> false + | Some [] -> true + | Some gids -> OpamStd.IntSet.(not (is_empty (inter (of_list gids) groups))) with e -> OpamStd.Exn.fatal e; false in let resolve ?dir env name = diff --git a/src/stubs/libacl/c-libraries.sexp.in b/src/stubs/libacl/c-libraries.sexp.in new file mode 100644 index 00000000000..3cb0baa5e78 --- /dev/null +++ b/src/stubs/libacl/c-libraries.sexp.in @@ -0,0 +1 @@ +(@CONF_LIBACL_LINK@) diff --git a/src/stubs/libacl/dune-libacl b/src/stubs/libacl/dune-libacl new file mode 100644 index 00000000000..9db0a443f46 --- /dev/null +++ b/src/stubs/libacl/dune-libacl @@ -0,0 +1,19 @@ +(library + (name opam_stubs_libacl) + (public_name opam-core.libacl) + (synopsis "OCaml Package Manager libacl C stubs") + (flags (:standard + (:include ../../ocaml-flags-standard.sexp) + (:include ../../ocaml-flags-configure.sexp) + (:include ../../ocaml-context-flags.sexp))) + (modules opamlibACL) + (c_names opamACL) + (c_flags (:standard + (:include ../c-flags.sexp))) + (c_library_flags (:include c-libraries.sexp)) + (wrapped false)) + +(rule + (targets c-libraries.sexp) + (mode fallback) + (action (with-stdout-to %{targets} (echo "()")))) diff --git a/src/stubs/libacl/opamACL.c b/src/stubs/libacl/opamACL.c new file mode 100644 index 00000000000..6ade803a480 --- /dev/null +++ b/src/stubs/libacl/opamACL.c @@ -0,0 +1,128 @@ +/**************************************************************************/ +/* */ +/* Copyright 2020 David Allsopp Ltd. */ +/* */ +/* All rights reserved. This file is distributed under the terms of the */ +/* GNU Lesser General Public License version 2.1, with the special */ +/* exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#include +#include +#include + +#define CAML_NAME_SPACE +#include +#include +#include + +#ifndef Val_none +#define Val_none Val_int(0) +#endif + +/* OPAM_get_acl_executable_info(file, owner) takes a filename and the uid of + * the file's owner (this saves a call to stat on both the OCaml and C sides). + * The result is: + * None - the process cannot execute file + * Some [] - the process can execute file + * Some gids - the process can execute file if it is any of these gids + */ +CAMLprim value OPAM_get_acl_executable_info(value file, value owner) +{ + CAMLparam2(file, owner); + CAMLlocal2(result, cell); + acl_t acl = acl_get_file(String_val(file), ACL_TYPE_ACCESS); + uid_t owner_uid = Int_val(owner); + uid_t uid = geteuid(); + + result = Val_none; + + if (acl) + { + acl_entry_t entry; + size_t siz; + + if (acl_get_entry(acl, ACL_FIRST_ENTRY, &entry) == 1) + { + int mask = 1; + int user = 0; + do + { + acl_tag_t tag; + acl_permset_t perms; + if (acl_get_tag_type(entry, &tag) == 0 && + acl_get_permset(entry, &perms) == 0) + { + void *qualifier = NULL; + int executable = acl_get_perm(perms, ACL_EXECUTE); + + switch(tag) + { + case ACL_USER: + if (executable && (qualifier = acl_get_qualifier(entry))) + { + uid_t entry_uid = *((uid_t *)qualifier); + /* NB ACL_USER entries do not override ACL_USER_OBJ */ + if (entry_uid != owner_uid && entry_uid == uid) + { + /* result = Some [] */ + if (!Is_block(result)) + { + result = caml_alloc_small(1, 0); + Field(result, 0) = Val_int(0); + } else { + caml_modify(&Field(result, 0), Val_int(0)); + } + user = 1; + } + } + break; + case ACL_GROUP: + if (!user && executable && (qualifier = acl_get_qualifier(entry))) + { + gid_t entry_gid = *((gid_t *)qualifier); + /* Construct a cons cell */ + cell = caml_alloc_small(2, 0); + Field(cell, 0) = Val_int(entry_gid); + if (Is_block(result)) + { + /* Put cons cell at head of existing list */ + Field(cell, 1) = Field(result, 0); + caml_modify(&Field(result, 0), cell); + } + else + { + /* result = Some [cell] */ + Field(cell, 1) = Val_int(0); + result = caml_alloc_small(1, 0); + Field(result, 0) = cell; + } + } + break; + case ACL_USER_OBJ: + case ACL_GROUP_OBJ: + /* These have already been done by the stat check */ + break; + case ACL_MASK: + if (!(mask = executable)) + { + result = Val_none; + } + break; + default: + /* ACL_UNDEFINED_TAG or ACL_OTHER */ + break; + } + + if (qualifier) + acl_free(qualifier); + } + } while (mask && acl_get_entry(acl, ACL_NEXT_ENTRY, &entry) == 1); + } + + acl_free((void *)acl); + } + + CAMLreturn(result); +} diff --git a/src/stubs/libacl/opamlibACL.ml b/src/stubs/libacl/opamlibACL.ml new file mode 100644 index 00000000000..a31e7cdf30e --- /dev/null +++ b/src/stubs/libacl/opamlibACL.ml @@ -0,0 +1,11 @@ +(**************************************************************************) +(* *) +(* Copyright 2020 David Allsopp Ltd. *) +(* *) +(* All rights reserved. This file is distributed under the terms of the *) +(* GNU Lesser General Public License version 2.1, with the special *) +(* exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +external get_acl_executable_info : string -> int -> int list option = "OPAM_get_acl_executable_info"