#!/bin/bash
#
# SPDX-License-Identifier: Apache-2.0 or MIT
#
# Copyright 2021 Sony Group Corporation
# Copyright 2023, 2025 Ali Polatel <alip@chesswob.org>

set -o errexit

# installed libseccomp version by default
DEFAULT_LIBSECCOMP_VER="v2.5.5"
TENTATIVE_HEAD_VER="2.9.9"
WORK_DIR="$(mktemp -d)"

function finish() {
    rm -rf "${WORK_DIR}"
}

trap finish EXIT

function build_and_install_gperf() {
    gperf_version="3.1"
    gperf_url="https://ftp.gnu.org/gnu/gperf"
    gperf_tarball="gperf-${gperf_version}.tar.gz"
    gperf_tarball_url="${gperf_url}/${gperf_tarball}"

    echo "Build and install gperf version ${gperf_version}"
    gperf_install_dir="$(mktemp -d)"
    curl -sLO "${gperf_tarball_url}"
    tar -xf "${gperf_tarball}"
    pushd "gperf-${gperf_version}"
    if ! ./configure --prefix="${gperf_install_dir}"; then
        find . -name config.log -exec cat '{}' '+'
        exit 1
    fi
    make
    make install
    export PATH=$PATH:"${gperf_install_dir}"/bin
    popd
    echo "Gperf installed successfully"
}

function build_and_install_libseccomp() {
    libseccomp_version=${opt_ver}
    libseccomp_install_dir=${opt_dir}
    libseccomp_cross_host=${opt_host}
    mkdir -p "${libseccomp_install_dir}"

    echo "Build and install libseccomp version ${libseccomp_version}"
    git clone --depth=1 'https://github.com/seccomp/libseccomp.git' --branch "${libseccomp_version}" --single-branch
    pushd libseccomp
    if [[ ${libseccomp_version} == 'main' ]]; then
        # Specify the tentative version of the libseccomp library because some
        # functions of the Rust bindings are restricted based on the version.
        sed -i "/^AC_INIT/ s/0.0.0/$TENTATIVE_HEAD_VER/" configure.ac
    fi

    # Avoid building documentation, tests and tools.
    sed -i \
        -e '/SUBDIRS\s*=/s/\(doc\|tests\|tools\)//g' \
        Makefile.am

    libtoolize
    ./autogen.sh
    cflags_def="${CFLAGS} -fPIC"
    chost=
    if [[ -n "${libseccomp_cross_host}" ]]; then
        chost="--host=${libseccomp_cross_host}"
    fi
    if [[ ${opt_musl} -eq 1 ]]; then
        # Set FORTIFY_SOURCE=1 because the musl-libc does not have some functions about FORTIFY_SOURCE=2
        cflags="-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1"
        if ! ./configure ${chost} \
                --prefix="${libseccomp_install_dir}" \
                CFLAGS="${cflags_def} ${cflags}" \
                --enable-static
        then
            find . -name config.log -exec cat '{}' '+'
            exit 1
        fi
    else
        if ! ./configure ${chost} \
            --prefix="${libseccomp_install_dir}" \
            CFLAGS="${cflags_def}" \
            --enable-static
        then
            find . -name config.log -exec cat '{}' '+'
            exit 1
        fi
    fi
    make
    make install
    popd
    echo 'Libseccomp installed successfully'
}

#
# Print out script usage details
#
function usage() {
cat <<EOF
Build and install libseccomp library from sources

USAGE:
  install_libseccomp [-m] [-v VERSION] [-i DIR]

OPTIONS:
  -h            : show this help message
  -m            : install libseccomp library for musl-libc [default: GNU-libc]
  -H [HOST]     : specify cross-compile host [default: native]
  -v [VERSION]  : specify the version of installed libseccomp library [default: ${DEFAULT_LIBSECCOMP_VER}]
                  If you want to install the HEAD of the libseccomp library (the main branch of the repository),
                  specify "main" and the version will be tentatively ${TENTATIVE_HEAD_VER}.
  -i [DIR]      : specify the directory for installing libseccomp library [default: /usr/local]
EOF
}

function main() {
    local opt_ver=${DEFAULT_LIBSECCOMP_VER}
    local opt_musl=0
    local opt_dir="/usr/local"
    local opt_host=

    while getopts "hmi:v:H:" opt; do
        case $opt in
            m)
                opt_musl=1
                ;;
            i)
                opt_dir="${OPTARG}"
                ;;
            v)
                opt_ver="${OPTARG}"
                ;;
            H)
		opt_host="${OPTARG}"
		;;
            h|*)
                usage
                exit 1
                ;;
        esac
    done

    pushd "${WORK_DIR}"
    # gperf is required for building the libseccomp.
    # Install it if it's not already in PATH.
    type -P gperf &>/dev/null || build_and_install_gperf
    build_and_install_libseccomp
    popd
}

main "$@"
