#!/bin/sh -ef # shellcheck source=/dev/null log() { # Print a message prettily. # # All messages are printed to stderr to allow the user to hide build # output which is the only thing printed to stdout. # # '${3:-->}': If the 3rd argument is missing, set prefix to '->'. # '${2:+colorb}': If the 2nd argument exists, set text style of '$1'. printf '%b%s %b%b%s%b %s\n' \ "$colory" "${3:-->}" "$colre" "${2:+$colorb}" "$1" "$colre" "$2" >&2 } version() { log "Carbs Packaging Tools" @VERSION@ exit 0 } trap_set() { # Function to set the trap value. case ${1:-cleanup} in cleanup) trap pkg_clean EXIT INT ;; block) trap '' INT ;; unset) trap - EXIT INT ;; esac } _readlinkf() { # Public domain POSIX sh readlink function by Koichi Nakashima [ "${1:-}" ] || return 1 max_symlinks=40 CDPATH='' # to avoid changing to an unexpected directory target=$1 [ -e "${target%/}" ] || target=${1%"${1##*[!/]}"} # trim trailing slashes [ -d "${target:-/}" ] && target="$target/" cd -P . 2>/dev/null || return 1 while [ "$max_symlinks" -ge 0 ] && max_symlinks=$((max_symlinks - 1)); do if [ ! "$target" = "${target%/*}" ]; then case $target in /*) cd -P "${target%/*}/" 2>/dev/null || break ;; *) cd -P "./${target%/*}" 2>/dev/null || break ;; esac target=${target##*/} fi if [ ! -L "$target" ]; then target="${PWD%/}${target:+/}${target}" printf '%s\n' "${target:-/}" return 0 fi # `ls -dl` format: "%s %u %s %s %u %s %s -> %s\n", # , , , , # , , , # https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html link=$(ls -dl -- "$target" 2>/dev/null) || break target=${link#*" $target -> "} done return 1 } # CPT Library does "lazy loading" of its functions. Meaning that functions are # defined, but the libraries containing the functions aren't loaded until one of # those functions are called. This should theoretically decrease the time it # takes to execute some script that uses only minimal amount of library # functions. When a function listed below is called, its definition is replaced # by the one in the loaded library, and executed with the same arguments. # @AUTOLOADS@ # main() { set -ef # Set the library directory if unset, assuming that it shares the same # prefix with the tool. [ "$CPT_LIBDIR" ] || CPT_LIBDIR=$(_readlinkf "$(command -v cpt-lib)") CPT_LIBDIR=${CPT_LIBDIR%/*} # If a parser definition exists, let's run it ourselves. This makes sure we # get the variables as soon as possible. command -v parser_definition >/dev/null && { eval "$(getoptions parser_definition parse "$0")" parse "$@" eval set -- "$REST" } # Create the cache directories for CPT and set the variables which point # to them. This is seperate from temporary directories created in # create_cache(). That's because we need these variables set on most # occasions. mkdir -p "${cac_dir:=${CPT_CACHE:=${XDG_CACHE_HOME:-$HOME/.cache}/cpt}}" \ "${src_dir:=$cac_dir/sources}" \ "${log_dir:=$cac_dir/logs}" \ "${bin_dir:=$cac_dir/bin}" # Set the location to the repository and package database. pkg_db=var/db/cpt/installed # The PID of the current shell process is used to isolate directories # to each specific CPT instance. This allows multiple package manager # instances to be run at once. Store the value in another variable so # that it doesn't change beneath us. pid=${CPT_PID:-$$} # Force the C locale to speed up things like 'grep' which disable unicode # etc when this is set. We don't need unicode and a speed up is always # welcome. export LC_ALL=C LANG=C # Catch errors and ensure that build files and directories are cleaned # up before we die. This occurs on 'Ctrl+C' as well as success and error. trap_set cleanup # Prefer GNU grep if installed as it is much much faster than busybox's # implementation. Very much worth it if you value performance over # POSIX correctness (grep quoted to avoid shellcheck false-positive). grep=$(command -v ggrep) || grep='grep' # Prefer libarchive tar or GNU tar if installed as they are much # much faster than busybox's implementation. Very much worth it if # you value performance. tar=$(command -v bsdtar || command -v gtar) || tar=tar # Figure out which 'sudo' command to use based on the user's choice or # what is available on the system. su=${CPT_SU:-$(command -v sls || command -v sudo || command -v doas)} || su=su # Store the date and time of script invocation to be used as the name # of the log files the package manager creates during builds. time=$(date '+%Y-%m-%d-%H:%M') # Use readelf for fixing dependencies if it is available, fallback to # ldd. readelf shows only the actual dependencies and doesn't include # the libraries required by the dependencies. elf_prog=${CPT_ELF:="$( command -v readelf || command -v llvm-readelf || command -v eu-readelf)"} || elf_prog=ldd # Make note of the user's current ID to do root checks later on. # This is used enough to warrant a place here. uid=$(id -u) # Save IFS, so we can restore it back to what it was before. old_ifs=$IFS # Make sure that the CPT_ROOT doesn't end with a '/'. This might # break some operations. CPT_ROOT=${CPT_ROOT%"${CPT_ROOT##*[!/]}"} # Define an optional sys_arch variable in order to provide # information to build files with architectural information. sys_arch=$(uname -m 2>/dev/null) ||: # Define this variable but don't create its directory structure from # the get go. It will be created as needed by package installation. sys_db=$CPT_ROOT/$pkg_db # This allows for automatic setup of a CPT chroot and will # do nothing on a normal system. mkdir -p "$CPT_ROOT/" 2>/dev/null ||: # Set a value for CPT_COMPRESS if it isn't set. : "${CPT_COMPRESS:=gz}" # Unless being piped or the user specifically doesn't want colors, set # colors. This can of course be overriden if the user specifically want # colors during piping. if { [ "$CPT_COLOR" != 0 ] && [ -t 1 ] ;} || [ "$CPT_COLOR" = 1 ]; then colory="\033[1;33m" colorb="\033[1;36m" colre="\033[m" fi }