#!/bin/sh # # SPDX-License-Identifier: ISC # # Copyright (c) 2010-2020 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. # # Build a binary package using polypkg # Usage: mkpkg [--debug] [--flavor flavor] [--platform platform] [--osversion ver] # # Make sure IFS is set to space, tab, newline in that order. space=' ' tab=' ' nl=' ' IFS=" $nl" # Parse arguments usage="usage: mkpkg [--debug] [--flavor flavor] [--platform platform] [--osversion ver]" debug=0 flavor=vanilla crossbuild=false while test $# -gt 0; do case "$1" in --debug) set -x debug=1 PPFLAGS="--debug${PPFLAGS+$space}${PPFLAGS}" ;; --flavor=?*) flavor=`echo "$1" | sed -n 's/^--flavor=\(.*\)/\1/p'` PPVARS="${PPVARS}${PPVARS+$space}flavor=$flavor" ;; --flavor) if [ $# -lt 2 ]; then echo "$usage" 1>&2 exit 1 fi flavor="$2" PPVARS="${PPVARS}${PPVARS+$space}flavor=$flavor" shift ;; --platform=?*) arg=`echo "$1" | sed -n 's/^--platform=\(.*\)/\1/p'` PPFLAGS="${PPFLAGS}${PPFLAGS+$space}--platform $arg" ;; --platform) if [ $# -lt 2 ]; then echo "$usage" 1>&2 exit 1 fi PPFLAGS="${PPFLAGS}${PPFLAGS+$space}--platform $2" shift ;; --osversion=?*) arg=`echo "$1" | sed -n 's/^--osversion=\(.*\)/\1/p'` osversion="$arg" ;; --osversion) if [ $# -lt 2 ]; then echo "$usage" 1>&2 exit 1 fi osversion="$2" shift ;; --build|--host) crossbuild=true configure_opts="${configure_opts}${configure_opts+$tab}$1" ;; *) # Pass unknown options to configure configure_opts="${configure_opts}${configure_opts+$tab}$1" ;; esac shift done scriptdir=`dirname $0` configure="${scriptdir}/../configure" : ${osversion="`$scriptdir/pp --probe`"} test -n "$osversion" || exit 1 osrelease=`echo "$osversion" | sed -e 's/^[^0-9]*//' -e 's/-.*$//'` : ${MAKE=make} # If using GNU make, set number of jobs if ${MAKE} --version 2>&1 | grep GNU >/dev/null; then NJOBS=0 case "`uname`" in Darwin) # macOS NJOBS=`sysctl -n hw.ncpu` ;; Linux) if [ -r /proc/cpuinfo ]; then for c in `sed -n 's/^cpu cores[ ]*: *//p' /proc/cpuinfo`; do NJOBS=`expr $NJOBS + $c` done fi ;; SunOS) # Solaris if [ -x /usr/sbin/psrinfo ]; then NJOBS=`/usr/sbin/psrinfo | wc -l` fi ;; HP-UX) NJOBS=`sar -Mu 1 1 | awk 'END {print NR-5}'` ;; AIX) NJOBS=`bindprocessor -q | awk '{print NF-4}'` ;; esac if [ $NJOBS -gt 1 ]; then make_opts="-j$NJOBS" fi fi # Choose compiler options by osversion if not cross-compiling. if [ "$crossbuild" = "false" ]; then case "$osversion" in macos*) # Use clang on macOS if present if [ -z "$CC" -a -x /usr/bin/clang ]; then CC=/usr/bin/clang; export CC fi ;; esac fi # Give configure a hint that we are building a package. # Some libc functions are only available on certain OS revisions. configure_opts="${configure_opts}${configure_opts+$tab}--enable-package-build" # Some systems don't have a recent enough OpenSSL for the I/O log server. with_openssl=false # Not all systems have Python 3. with_python=false # Choose configure options by osversion. # We use the same configure options as vendor packages when possible. case "$osversion" in centos*|rhel*|f[0-9]*) case "$osversion" in centos*|rhel*) osmajor=`sed -n -e 's/^.*release \([0-9]*\)[^0-9].*$/\1/p' /etc/redhat-release` if [ $osmajor -ge 4 ]; then # RHEL 4 and up support SELinux with_selinux=true if [ $osmajor -ge 5 ]; then # RHEL 5 and up has audit support and uses a # separate PAM config file for "sudo -i". with_linux_audit=true with_pam_login=true if [ $osmajor -ge 6 ]; then # RHEL 6 and above builds sudo with SSSD support with_sssd=true # RHEL 6 and above use /etc/sudo-ldap.conf with_sudo_ldap_conf=true # Encrypted remote I/O log support. with_openssl=true fi if [ $osmajor -ge 7 ]; then # Python plugins with_python=true fi fi fi ;; f[0-9]*) # XXX - investigate which features were in which fedora version with_selinux=true with_linux_audit=true with_pam_login=true with_sssd=true with_openssl=true ;; esac if [ X"$with_selinux" = X"true" ]; then configure_opts="${configure_opts}${configure_opts+$tab}--with-selinux" fi if [ X"$with_linux_audit" = X"true" ]; then configure_opts="${configure_opts}${configure_opts+$tab}--with-linux-audit" PPVARS="${PPVARS}${PPVARS+$space}linux_audit=1.4.0" fi if [ X"$with_pam_login" = X"true" ]; then configure_opts="${configure_opts}${configure_opts+$tab}--with-pam-login" fi if [ X"$with_sssd" = X"true" ]; then configure_opts="${configure_opts}${configure_opts+$tab}--with-sssd" if test "`getconf LONG_BIT`" = "64"; then # SSSD backend needs to know where to find the sssd lib configure_opts="${configure_opts}${configure_opts+$tab}--with-sssd-lib=/usr/lib64" fi fi if [ X"$with_sudo_ldap_conf" = X"true" ]; then configure_opts="${configure_opts}${configure_opts+$tab}--with-ldap-conf-file=/etc/sudo-ldap.conf" fi # Note, must indent with tabs, not spaces due to IFS trickery configure_opts="--prefix=/usr --with-logging=syslog --with-logfac=authpriv --with-pam --enable-zlib=system --with-editor=/bin/vi --with-env-editor --with-ignore-dot --with-tty-tickets --with-ldap --with-passprompt=[sudo] password for %p: --with-sendmail=/usr/sbin/sendmail $configure_opts" ;; sles*) if [ $osrelease -ge 10 ]; then if [ $osrelease -ge 11 ]; then # SLES 11 and higher have SELinux configure_opts="${configure_opts}${configure_opts+$tab}--with-selinux" fi if [ $osrelease -ge 12 ]; then # Encrypted remote I/O log support. with_openssl=true # Python plugins with_python=true fi fi # SuSE doesn't have /usr/libexec libexec=lib case "$osversion" in *64*) gcc -v 2>&1 | grep "with-cpu=[^ ]*32" >/dev/null || libexec=lib64 ;; esac # Note, must indent with tabs, not spaces due to IFS trickery # XXX - SuSE uses secure path but only for env_reset configure_opts="--prefix=/usr --libexecdir=/usr/$libexec --with-logging=syslog --with-logfac=auth --with-all-insults --with-ignore-dot --with-tty-tickets --enable-shell-sets-home --with-sudoers-mode=0440 --with-pam --enable-zlib=system --with-ldap --with-env-editor --with-passprompt=%p\'s password: --with-sendmail=/usr/sbin/sendmail $configure_opts" make_opts="${make_opts}${make_opts+ }"'docdir=$(datarootdir)/doc/packages/$(PACKAGE_TARNAME)' ;; deb*|ubu*) # Encrypted remote I/O log support. with_openssl=true # Python plugins with_python=true # Man pages should be compressed in .deb files export MANCOMPRESS='gzip -9' export MANCOMPRESSEXT='.gz' # If Ubuntu, add --enable-admin-flag case "$osversion" in ubu*) configure_opts="${configure_opts}${configure_opts+$tab}--enable-admin-flag${tab}--without-lecture" ;; esac # Newer Debian uses arch-specific lib dirs MULTIARCH=`dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null` # Note, must indent with tabs, not spaces due to IFS trickery if test "$flavor" = "ldap"; then configure_opts="${configure_opts}${configure_opts+$tab}--with-ldap --with-ldap-conf-file=/etc/sudo-ldap.conf" else configure_opts="${configure_opts}${configure_opts+$tab}--with-sssd" if test -n "$MULTIARCH"; then # SSSD backend needs to know where to find the sssd lib configure_opts="${configure_opts}${configure_opts+$tab}--with-sssd-lib=/usr/lib/$MULTIARCH" fi fi configure_opts="--prefix=/usr --with-all-insults --with-pam --enable-zlib=system --with-fqdn --with-logging=syslog --with-logfac=authpriv --with-env-editor --with-editor=/usr/bin/editor --with-timeout=15 --with-password-timeout=0 --with-passprompt=[sudo] password for %p: --disable-root-mailer --with-sendmail=/usr/sbin/sendmail --mandir=/usr/share/man --libexecdir=/usr/lib --with-selinux --with-linux-audit $configure_opts" # Use correct libaudit dependency for f in /lib/${MULTIARCH}${MULTIARCH:+/}libaudit.so.[0-9]* /lib/libaudit.so.[0-9]*; do if test -f "$f"; then linux_audit=`dpkg-query -S "$f" 2>/dev/null | sed -n 's/:.*//p'` test -n "$linux_audit" && break; fi done if [ -z "$linux_audit" ]; then echo "unable to determine package for libaudit" 1>&2 exit 1 fi PPVARS="${PPVARS}${PPVARS+$space}linux_audit=$linux_audit" # Use correct libssl dependency libssl_dep=`dpkg-query -S /usr/lib/${MULTIARCH}${MULTIARCH:+/}libssl.so.1.[0-9]* /lib/${MULTIARCH}${MULTIARCH:+/}libssl.so.1.[0-9]* 2>/dev/null | sort -rn | awk -F: '{ print $1; exit }'` if [ -z "$libssl_dep" ]; then echo "unable to determine package for libssl" 1>&2 exit 1 fi PPVARS="${PPVARS}${PPVARS+$space}libssl_dep=$libssl_dep" ;; macos*) # TODO: openssl (homebrew?) case "$osversion" in macos10[0-6]-i386|macos10[0-6]-x86_64) # Build intel universal binaries for 10.6 and below ARCH_FLAGS="-arch i386 -arch x86_64" ;; macos11*) # Build arm64/x86_64 universal binaries for macOS 11 ARCH_FLAGS="-arch arm64 -arch x86_64" ;; esac if test "${osversion}" != "`$scriptdir/pp --probe`"; then sdkvers=`echo "${osversion}" | sed 's/^macos\([0-9][0-9]\)\([0-9]*\)-.*$/\1.\2/'` # SDKs may be under Xcode.app or CommandLineTools (for non-Xcode) if [ -d "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs" ]; then SDK_DIR="/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs" elif [ -d "/Library/Developer/CommandLineTools/SDKs" ]; then SDK_DIR="/Library/Developer/CommandLineTools/SDKs" else echo "unable to find macOS SDKs directory" 1>&2 exit 1 fi SDK_DIR="${SDK_DIR}/MacOSX${sdkvers}.sdk" if test -d "${SDK_DIR}"; then SDK_FLAGS="-isysroot ${SDK_DIR} -mmacosx-version-min=${sdkvers}" else echo "unable to find SDKs directory for macOS $sdkvers" 1>&2 exit 1 fi fi export CFLAGS="-O2 -g $ARCH_FLAGS $SDK_FLAGS" export LDFLAGS="$ARCH_FLAGS $SDK_FLAGS" # Note, must indent with tabs, not spaces due to IFS trickery configure_opts="--with-pam --with-bsm-audit --without-tty-tickets --enable-zlib=system --with-ldap --with-insults=disabled --with-logging=syslog --with-logfac=authpriv --with-editor=/usr/bin/vim --with-env-editor $configure_opts" ;; aix*) # TODO: openssl (AIX freeware?) # Use -gxcoff with gcc instead of -g for dbx-style debugging symbols. if test -z "$CC" && gcc -v >/dev/null 2>&1; then CFLAGS="-O2 -gxcoff"; export CFLAGS fi # Note, must indent with tabs, not spaces due to IFS trickery # Note: we include our own zlib instead of relying on the # AIX freeware version being installed. configure_opts=" --prefix=/opt/freeware --mandir=/opt/freeware/man --with-insults=disabled --with-logging=syslog --with-logfac=auth --with-editor=/usr/bin/vi --with-env-editor --enable-zlib=builtin --disable-nls --with-sendmail=/usr/sbin/sendmail $configure_opts" PPVARS="${PPVARS}${PPVARS+$space}aix_freeware=true" ;; *) # For Solaris, add project support and use let configure choose zlib. # For all others, use the builtin zlib and disable NLS support. case "$osversion" in sol*) configure_opts="${configure_opts}${configure_opts+$tab}--with-project" if [ $osrelease -ge 11 ]; then # Build 64-bit binaries on Solaris 11 and above. CFLAGS="-O2 -g -m64"; export CFLAGS LDFLAGS="-m64"; export LDFLAGS # Solaris audit is not supported by Illumos if test X"`uname -o 2>/dev/null`" = X"illumos"; then configure_opts="${configure_opts}${configure_opts+$tab}--with-bsm-audit" else configure_opts="${configure_opts}${configure_opts+$tab}--with-solaris-audit" fi # Encrypted remote I/O log support. with_openssl=true # Python plugins with_python=true # We prefer the system version of python3 to the # csw one (which may be 32-bit) if [ -z "$PYTHON" ]; then if [ -x /usr/bin/python3 ]; then PYTHON="/usr/bin/python3"; export PYTHON else # Sometimes the /usr/bin/python3 is missing for f in /usr/bin/python3.9 /usr/bin/python3.8 /usr/bin/python3.7 /usr/bin/python3.6 /usr/bin/python3.5 /usr/bin/python3.4 /usr/bin/python3.3 /usr/bin/python3.2 /usr/bin/python3.1 /usr/bin/python3.0; do if [ -x $f ]; then PYTHON="$f"; export PYTHON break fi done fi fi fi ;; hpux*-ia64) # Build 64-bit binaries on HP-UX ia64 if test -z "$CC" && gcc -v >/dev/null 2>&1; then CC="gcc -mlp64"; export CC fi # TODO: openssl configure_opts="${configure_opts}${configure_opts+$tab}--enable-zlib=builtin${tab}--disable-nls" ;; *) # TODO: openssl configure_opts="${configure_opts}${configure_opts+$tab}--enable-zlib=builtin${tab}--disable-nls" ;; esac if test "$flavor" = "ldap"; then configure_opts="${configure_opts}${configure_opts+$tab}--with-ldap" fi # Note, must indent with tabs, not spaces due to IFS trickery configure_opts=" --with-insults=disabled --with-logging=syslog --with-logfac=auth --with-editor=/usr/bin/vim:/usr/bin/vi:/bin/vi --with-env-editor $configure_opts" ;; esac # Don't enable OpenSSL if user disabled it. case "$configure_opts" in *--disable-openssl*) with_openssl=false;; esac if [ X"$with_openssl" = X"true" ]; then configure_opts="${configure_opts}${configure_opts+$tab}--enable-openssl" fi if [ X"$with_python" = X"true" ]; then configure_opts="${configure_opts}${configure_opts+$tab}--enable-python" fi # The postinstall script will create tmpfiles.d/sudo.conf for us configure_opts="${configure_opts}${configure_opts+$tab}--disable-tmpfiles.d" # Remove spaces from IFS when setting $@ so that passprompt may include them OIFS="$IFS" IFS=" $nl" set -- $configure_opts $extra_opts IFS="$OIFS" if [ -r Makefile ]; then ${MAKE} $make_opts distclean fi ${configure} "$@" || exit 1 ${MAKE} $make_opts && ${MAKE} $make_opts PPFLAGS="$PPFLAGS" PPVARS="$PPVARS" package test $debug -eq 0 && rm -rf destdir