changelog shortlog graph tags branches files raw help

Mercurial > infra / changeset: bootstrap mv

changeset 239: 7c6e3bbfe8cd
parent 238: 489ae684b01a
child 240: 5d84c4505479
author: Richard Westhaver <ellis@rwest.io>
date: Tue, 28 May 2024 01:40:54 +0000
files: bootstrap.sh check.sh containers/Containerfile.box install.sh
description: bootstrap mv
     1.1--- a/bootstrap.sh	Mon May 27 23:09:57 2024 +0000
     1.2+++ b/bootstrap.sh	Tue May 28 01:40:54 2024 +0000
     1.3@@ -1,1 +1,352 @@
     1.4-#!/usr/bin/env sh
     1.5+#!/bin/sh
     1.6+set -eu
     1.7+main() {
     1.8+  . ./check.sh
     1.9+  download --check
    1.10+  local _arch=$(_read arch | tr -d '"')
    1.11+  local _ext=""
    1.12+  case "$_arch" in
    1.13+    *windows*)
    1.14+      _ext=".exe"
    1.15+      ;;
    1.16+  esac
    1.17+  local _url="https://packy.compiler.company/dist/${_arch}"
    1.18+  local _stash
    1.19+  if ! _stash=".stash"; then
    1.20+    # Because the previous command ran in a subshell, we must manually
    1.21+    # propagate exit status.
    1.22+    exit 1
    1.23+  fi
    1.24+  ensure mkdir -p "${_stash}/src"
    1.25+  ensure mkdir -p "${_stash}/bin"
    1.26+  local _sk_url="${_url}/bin/sk"
    1.27+  local _sbcl_url="${_url}/pack/sbcl.tar.zst"
    1.28+  local _rocksdb_url="${_url}/pack/rocksdb.tar.zst"
    1.29+  ensure download "$_sbcl_url" "${_stash}/src/sbcl.tar.zst" "$_arch"
    1.30+  ensure download "$_rocksdb_url" "${_stash}/src/rocksdb.tar.zst" "$_arch"
    1.31+  ensure download "$_sk_url" "${_stash}/bin/sk" "$_arch"
    1.32+}
    1.33+
    1.34+_read() {
    1.35+  grep ":$1" $INFRA_HOST_CONFIG | cut -d' ' -f 2-
    1.36+}
    1.37+
    1.38+say() {
    1.39+  printf 'bootstrap.sh: %s\n' "$1"
    1.40+}
    1.41+
    1.42+err() {
    1.43+  say "$1" >&2
    1.44+  exit 1
    1.45+}
    1.46+
    1.47+check_cmd() {
    1.48+  command -v "$1" > /dev/null 2>&1
    1.49+}
    1.50+
    1.51+need_cmd() {
    1.52+  if ! check_cmd "$1"; then
    1.53+    err "need '$1' (command not found)"
    1.54+  fi
    1.55+}
    1.56+
    1.57+# Run a command that should never fail. If the command fails execution
    1.58+# will immediately terminate with an error showing the failing
    1.59+# command.
    1.60+ensure() {
    1.61+  if ! "$@"; then err "command failed: $*"; fi
    1.62+}
    1.63+
    1.64+# Check if curl supports the --retry flag, then pass it to the curl invocation.
    1.65+check_curl_for_retry_support() {
    1.66+  local _retry_supported=""
    1.67+  # "unspecified" is for arch, allows for possibility old OS using macports, homebrew, etc.
    1.68+  if check_help_for "notspecified" "curl" "--retry"; then
    1.69+    _retry_supported="--retry 3"
    1.70+    if check_help_for "notspecified" "curl" "--continue-at"; then
    1.71+      # "-C -" tells curl to automatically find where to resume the download when retrying.
    1.72+      _retry_supported="--retry 3 -C -"
    1.73+    fi
    1.74+  fi
    1.75+
    1.76+  RETVAL="$_retry_supported"
    1.77+}
    1.78+
    1.79+# Return cipher suite string specified by user, otherwise return strong TLS 1.2-1.3 cipher suites
    1.80+# if support by local tools is detected. Detection currently supports these curl backends:
    1.81+# GnuTLS and OpenSSL (possibly also LibreSSL and BoringSSL). Return value can be empty.
    1.82+get_ciphersuites_for_curl() {
    1.83+  if [ -n "${TLS_CIPHERSUITES-}" ]; then
    1.84+    # user specified custom cipher suites, assume they know what they're doing
    1.85+    RETVAL="$TLS_CIPHERSUITES"
    1.86+    return
    1.87+  fi
    1.88+
    1.89+  local _openssl_syntax="no"
    1.90+  local _gnutls_syntax="no"
    1.91+  local _backend_supported="yes"
    1.92+  if curl -V | grep -q ' OpenSSL/'; then
    1.93+    _openssl_syntax="yes"
    1.94+  elif curl -V | grep -iq ' LibreSSL/'; then
    1.95+    _openssl_syntax="yes"
    1.96+  elif curl -V | grep -iq ' BoringSSL/'; then
    1.97+    _openssl_syntax="yes"
    1.98+  elif curl -V | grep -iq ' GnuTLS/'; then
    1.99+    _gnutls_syntax="yes"
   1.100+  else
   1.101+    _backend_supported="no"
   1.102+  fi
   1.103+
   1.104+  local _args_supported="no"
   1.105+  if [ "$_backend_supported" = "yes" ]; then
   1.106+    # "unspecified" is for arch, allows for possibility old OS using macports, homebrew, etc.
   1.107+    if check_help_for "notspecified" "curl" "--tlsv1.2" "--ciphers" "--proto"; then
   1.108+      _args_supported="yes"
   1.109+    fi
   1.110+  fi
   1.111+
   1.112+  local _cs=""
   1.113+  if [ "$_args_supported" = "yes" ]; then
   1.114+    if [ "$_openssl_syntax" = "yes" ]; then
   1.115+      _cs=$(get_strong_ciphersuites_for "openssl")
   1.116+    elif [ "$_gnutls_syntax" = "yes" ]; then
   1.117+      _cs=$(get_strong_ciphersuites_for "gnutls")
   1.118+    fi
   1.119+  fi
   1.120+
   1.121+  RETVAL="$_cs"
   1.122+}
   1.123+
   1.124+# Return cipher suite string specified by user, otherwise return strong TLS 1.2-1.3 cipher suites
   1.125+# if support by local tools is detected. Detection currently supports these wget backends:
   1.126+# GnuTLS and OpenSSL (possibly also LibreSSL and BoringSSL). Return value can be empty.
   1.127+get_ciphersuites_for_wget() {
   1.128+  if [ -n "${TLS_CIPHERSUITES-}" ]; then
   1.129+    # user specified custom cipher suites, assume they know what they're doing
   1.130+    RETVAL="$TLS_CIPHERSUITES"
   1.131+    return
   1.132+  fi
   1.133+
   1.134+  local _cs=""
   1.135+  if wget -V | grep -q '\-DHAVE_LIBSSL'; then
   1.136+    # "unspecified" is for arch, allows for possibility old OS using macports, homebrew, etc.
   1.137+    if check_help_for "notspecified" "wget" "TLSv1_2" "--ciphers" "--https-only" "--secure-protocol"; then
   1.138+      _cs=$(get_strong_ciphersuites_for "openssl")
   1.139+    fi
   1.140+  elif wget -V | grep -q '\-DHAVE_LIBGNUTLS'; then
   1.141+    # "unspecified" is for arch, allows for possibility old OS using macports, homebrew, etc.
   1.142+    if check_help_for "notspecified" "wget" "TLSv1_2" "--ciphers" "--https-only" "--secure-protocol"; then
   1.143+      _cs=$(get_strong_ciphersuites_for "gnutls")
   1.144+    fi
   1.145+  fi
   1.146+
   1.147+  RETVAL="$_cs"
   1.148+}
   1.149+
   1.150+check_help_for() {
   1.151+    local _arch
   1.152+    local _cmd
   1.153+    local _arg
   1.154+    _arch="$1"
   1.155+    shift
   1.156+    _cmd="$1"
   1.157+    shift
   1.158+
   1.159+    local _category
   1.160+    if "$_cmd" --help | grep -q 'For all options use the manual or "--help all".'; then
   1.161+      _category="all"
   1.162+    else
   1.163+      _category=""
   1.164+    fi
   1.165+
   1.166+    case "$_arch" in
   1.167+
   1.168+        *darwin*)
   1.169+        if check_cmd sw_vers; then
   1.170+            case $(sw_vers -productVersion) in
   1.171+                10.*)
   1.172+                    # If we're running on macOS, older than 10.13, then we always
   1.173+                    # fail to find these options to force fallback
   1.174+                    if [ "$(sw_vers -productVersion | cut -d. -f2)" -lt 13 ]; then
   1.175+                        # Older than 10.13
   1.176+                        echo "Warning: Detected macOS platform older than 10.13"
   1.177+                        return 1
   1.178+                    fi
   1.179+                    ;;
   1.180+                11.*)
   1.181+                    # We assume Big Sur will be OK for now
   1.182+                    ;;
   1.183+                *)
   1.184+                    # Unknown product version, warn and continue
   1.185+                    echo "Warning: Detected unknown macOS major version: $(sw_vers -productVersion)"
   1.186+                    echo "Warning TLS capabilities detection may fail"
   1.187+                    ;;
   1.188+            esac
   1.189+        fi
   1.190+        ;;
   1.191+
   1.192+    esac
   1.193+
   1.194+    for _arg in "$@"; do
   1.195+        if ! "$_cmd" --help "$_category" | grep -q -- "$_arg"; then
   1.196+            return 1
   1.197+        fi
   1.198+    done
   1.199+
   1.200+    true # not strictly needed
   1.201+}
   1.202+
   1.203+# Return strong TLS 1.2-1.3 cipher suites in OpenSSL or GnuTLS syntax. TLS 1.2
   1.204+# excludes non-ECDHE and non-AEAD cipher suites. DHE is excluded due to bad
   1.205+# DH params often found on servers (see RFC 7919). Sequence matches or is
   1.206+# similar to Firefox 68 ESR with weak cipher suites disabled via about:config.
   1.207+# $1 must be openssl or gnutls.
   1.208+get_strong_ciphersuites_for() {
   1.209+  if [ "$1" = "openssl" ]; then
   1.210+    # OpenSSL is forgiving of unknown values, no problems with TLS 1.3 values on versions that don't support it yet.
   1.211+    echo "TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384"
   1.212+  elif [ "$1" = "gnutls" ]; then
   1.213+    # GnuTLS isn't forgiving of unknown values, so this may require a GnuTLS version that supports TLS 1.3 even if wget doesn't.
   1.214+    # Begin with SECURE128 (and higher) then remove/add to build cipher suites. Produces same 9 cipher suites as OpenSSL but in slightly different order.
   1.215+    echo "SECURE128:-VERS-SSL3.0:-VERS-TLS1.0:-VERS-TLS1.1:-VERS-DTLS-ALL:-CIPHER-ALL:-MAC-ALL:-KX-ALL:+AEAD:+ECDHE-ECDSA:+ECDHE-RSA:+AES-128-GCM:+CHACHA20-POLY1305:+AES-256-GCM"
   1.216+  fi
   1.217+}
   1.218+
   1.219+check_proc() {
   1.220+  # Check for /proc by looking for the /proc/self/exe link
   1.221+  # This is only run on Linux
   1.222+  if ! test -L /proc/self/exe ; then
   1.223+    err "fatal: Unable to find /proc/self/exe.  Is /proc mounted?  Installation cannot proceed without /proc."
   1.224+  fi
   1.225+}
   1.226+
   1.227+get_bitness() {
   1.228+  need_cmd head
   1.229+  # Architecture detection without dependencies beyond coreutils.
   1.230+  # ELF files start out "\x7fELF", and the following byte is
   1.231+  #   0x01 for 32-bit and
   1.232+  #   0x02 for 64-bit.
   1.233+  # The printf builtin on some shells like dash only supports octal
   1.234+  # escape sequences, so we use those.
   1.235+  local _current_exe_head
   1.236+  _current_exe_head=$(head -c 5 /proc/self/exe )
   1.237+  if [ "$_current_exe_head" = "$(printf '\177ELF\001')" ]; then
   1.238+    echo 32
   1.239+  elif [ "$_current_exe_head" = "$(printf '\177ELF\002')" ]; then
   1.240+    echo 64
   1.241+  else
   1.242+    err "unknown platform bitness"
   1.243+  fi
   1.244+}
   1.245+
   1.246+is_host_amd64_elf() {
   1.247+  need_cmd head
   1.248+  need_cmd tail
   1.249+  # ELF e_machine detection without dependencies beyond coreutils.
   1.250+  # Two-byte field at offset 0x12 indicates the CPU,
   1.251+  # but we're interested in it being 0x3E to indicate amd64, or not that.
   1.252+  local _current_exe_machine
   1.253+  _current_exe_machine=$(head -c 19 /proc/self/exe | tail -c 1)
   1.254+  [ "$_current_exe_machine" = "$(printf '\076')" ]
   1.255+}
   1.256+
   1.257+get_endianness() {
   1.258+  local cputype=$1
   1.259+  local suffix_eb=$2
   1.260+  local suffix_el=$3
   1.261+
   1.262+  # detect endianness without od/hexdump, like get_bitness() does.
   1.263+  need_cmd head
   1.264+  need_cmd tail
   1.265+
   1.266+  local _current_exe_endianness
   1.267+  _current_exe_endianness="$(head -c 6 /proc/self/exe | tail -c 1)"
   1.268+  if [ "$_current_exe_endianness" = "$(printf '\001')" ]; then
   1.269+    echo "${cputype}${suffix_el}"
   1.270+  elif [ "$_current_exe_endianness" = "$(printf '\002')" ]; then
   1.271+    echo "${cputype}${suffix_eb}"
   1.272+  else
   1.273+    err "unknown platform endianness"
   1.274+  fi
   1.275+}
   1.276+
   1.277+# This wraps curl or wget. Try curl first, if not installed,
   1.278+# use wget instead.
   1.279+download() {
   1.280+  local _dld
   1.281+  local _ciphersuites
   1.282+  local _err
   1.283+  local _status
   1.284+  local _retry
   1.285+  if check_cmd curl; then
   1.286+    _dld=curl
   1.287+  elif check_cmd wget; then
   1.288+    _dld=wget
   1.289+  else
   1.290+    _dld='curl or wget' # to be used in error message of need_cmd
   1.291+  fi
   1.292+
   1.293+  if [ "$1" = --check ]; then
   1.294+    need_cmd "$_dld"
   1.295+  elif [ "$_dld" = curl ]; then
   1.296+    check_curl_for_retry_support
   1.297+    _retry="$RETVAL"
   1.298+    get_ciphersuites_for_curl
   1.299+    _ciphersuites="$RETVAL"
   1.300+    if [ -n "$_ciphersuites" ]; then
   1.301+      _err=$(curl $_retry --proto '=https' --tlsv1.2 --ciphers "$_ciphersuites" --silent --show-error --fail --location "$1" --output "$2" 2>&1)
   1.302+      _status=$?
   1.303+    else
   1.304+      echo "Warning: Not enforcing strong cipher suites for TLS, this is potentially less secure"
   1.305+      if ! check_help_for "$3" curl --proto --tlsv1.2; then
   1.306+        echo "Warning: Not enforcing TLS v1.2, this is potentially less secure"
   1.307+        _err=$(curl $_retry --silent --show-error --fail --location "$1" --output "$2" 2>&1)
   1.308+        _status=$?
   1.309+      else
   1.310+        _err=$(curl $_retry --proto '=https' --tlsv1.2 --silent --show-error --fail --location "$1" --output "$2" 2>&1)
   1.311+        _status=$?
   1.312+      fi
   1.313+    fi
   1.314+    if [ -n "$_err" ]; then
   1.315+      echo "$_err" >&2
   1.316+      if echo "$_err" | grep -q 404$; then
   1.317+        err "installer for platform '$3' not found, this may be unsupported"
   1.318+      fi
   1.319+    fi
   1.320+    return $_status
   1.321+  elif [ "$_dld" = wget ]; then
   1.322+    if [ "$(wget -V 2>&1|head -2|tail -1|cut -f1 -d" ")" = "BusyBox" ]; then
   1.323+      echo "Warning: using the BusyBox version of wget.  Not enforcing strong cipher suites for TLS or TLS v1.2, this is potentially less secure"
   1.324+      _err=$(wget "$1" -O "$2" 2>&1)
   1.325+      _status=$?
   1.326+    else
   1.327+      get_ciphersuites_for_wget
   1.328+      _ciphersuites="$RETVAL"
   1.329+      if [ -n "$_ciphersuites" ]; then
   1.330+        _err=$(wget --https-only --secure-protocol=TLSv1_2 --ciphers "$_ciphersuites" "$1" -O "$2" 2>&1)
   1.331+        _status=$?
   1.332+      else
   1.333+        echo "Warning: Not enforcing strong cipher suites for TLS, this is potentially less secure"
   1.334+        if ! check_help_for "$3" wget --https-only --secure-protocol; then
   1.335+          echo "Warning: Not enforcing TLS v1.2, this is potentially less secure"
   1.336+          _err=$(wget "$1" -O "$2" 2>&1)
   1.337+          _status=$?
   1.338+        else
   1.339+          _err=$(wget --https-only --secure-protocol=TLSv1_2 "$1" -O "$2" 2>&1)
   1.340+          _status=$?
   1.341+        fi
   1.342+      fi
   1.343+    fi
   1.344+    if [ -n "$_err" ]; then
   1.345+      echo "$_err" >&2
   1.346+      if echo "$_err" | grep -q ' 404 Not Found$'; then
   1.347+        err "installer for platform '$3' not found, this may be unsupported"
   1.348+      fi
   1.349+    fi
   1.350+    return $_status
   1.351+  else
   1.352+    err "Unknown downloader"   # should not reach here
   1.353+  fi
   1.354+}
   1.355+
   1.356+main "$@" || exit 1
     2.1--- a/check.sh	Mon May 27 23:09:57 2024 +0000
     2.2+++ b/check.sh	Tue May 28 01:40:54 2024 +0000
     2.3@@ -16,8 +16,8 @@
     2.4   need_cmd awk
     2.5   need_cmd head
     2.6   need_cmd tail
     2.7-  host_config_file=$(cat /proc/sys/kernel/hostname).sxp
     2.8-  rm -f $host_config_file
     2.9+  export INFRA_HOST_CONFIG=$(cat /proc/sys/kernel/hostname).sxp
    2.10+  rm -f $INFRA_HOST_CONFIG
    2.11   check_mem
    2.12   local _mem_total="$RETVAL"
    2.13   check_disk
    2.14@@ -41,7 +41,6 @@
    2.15     *)
    2.16       _write ":ext nil"
    2.17   esac
    2.18-  print_env
    2.19 }
    2.20 
    2.21 say() {
    2.22@@ -53,7 +52,7 @@
    2.23 }
    2.24 
    2.25 _write() {
    2.26-  say "$1" >> $host_config_file
    2.27+  say "$1" >> $INFRA_HOST_CONFIG
    2.28 }
    2.29 
    2.30 err() {
     3.1--- a/containers/Containerfile.box	Mon May 27 23:09:57 2024 +0000
     3.2+++ b/containers/Containerfile.box	Tue May 28 01:40:54 2024 +0000
     3.3@@ -1,7 +1,5 @@
     3.4 FROM localhost/archlinux:latest
     3.5 RUN --network=host pacman -Sy uutils-coreutils sysstat iotop imagemagick giflib libgccjit libxaw snappy sbcl liburing libxkbcommon nuklear --noconfirm
     3.6-# VOLUME /opt/store
     3.7-# VOLUME /opt/stash
     3.8 # custom
     3.9 ARG DEV=dev
    3.10 ARG DEV_HOME=/home/${DEV}
    3.11@@ -15,27 +13,22 @@
    3.12 ENV CARGO_HOME="/usr/local/share/cargo"
    3.13 ENV RUSTUP_HOME="/usr/local/share/rustup"
    3.14 # stage1
    3.15-RUN sh scripts/get-sk.sh /usr/local/bin
    3.16-RUN sk make rustup
    3.17+RUN ./bootstrap.sh
    3.18 ENV PATH="$PATH:/usr/local/share/cargo/bin"
    3.19+RUN .stash/bin/sk make rustup
    3.20 RUN rustup update
    3.21 # dev rustc components
    3.22 RUN rustup default nightly
    3.23 RUN rustup component add --toolchain nightly rust-src rust-analyzer rustc-dev llvm-tools-preview
    3.24-# RUN sh scripts/install-nushell-pack.sh
    3.25-# RUN sh scripts/install-emacs-pack.sh
    3.26-# RUN sh scripts/install-sbcl-pack.sh
    3.27-# RUN sh scripts/install-rocksdb-pack.sh
    3.28-# RUN sh scripts/install-cargo-tools.sh
    3.29-RUN sk make sbcl
    3.30-RUN sk make quicklisp
    3.31-RUN sk make sbcl-install
    3.32-RUN sk make tree-sitter
    3.33-RUN sk make tree-sitter-langs
    3.34-RUN sk make emacs-mini
    3.35-RUN sk make emacs-install
    3.36-RUN sk make rocksdb
    3.37-RUN sk make rocksdb-install
    3.38+RUN .stash/bin/sk make sbcl
    3.39+RUN .stash/bin/sk make quicklisp
    3.40+RUN .stash/bin/sk make sbcl-install
    3.41+RUN .stash/bin/sk make tree-sitter
    3.42+RUN .stash/bin/sk make tree-sitter-langs
    3.43+RUN .stash/bin/sk make emacs-mini
    3.44+RUN .stash/bin/sk make emacs-install
    3.45+RUN .stash/bin/sk make rocksdb
    3.46+RUN .stash/bin/sk make rocksdb-install
    3.47 #ADD etc/sbclrc /etc/sbclrc
    3.48 #COPY etc/skel/ /etc/skel/
    3.49 #ADD etc/shells /etc/
     4.1--- a/install.sh	Mon May 27 23:09:57 2024 +0000
     4.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.3@@ -1,566 +0,0 @@
     4.4-#!/bin/sh
     4.5-set -eu
     4.6-main() {
     4.7-  download --check
     4.8-
     4.9-  get_architecture || return 1
    4.10-  local _arch="$RETVAL"
    4.11-  assert_nz "$_arch" "arch"
    4.12-
    4.13-  local _ext=""
    4.14-  case "$_arch" in
    4.15-    *windows*)
    4.16-      _ext=".exe"
    4.17-      ;;
    4.18-  esac
    4.19-
    4.20-  local _url="https://packy.compiler.company/dist/${_arch}"
    4.21-  local _stash
    4.22-  if ! _stash=".stash"; then
    4.23-    # Because the previous command ran in a subshell, we must manually
    4.24-    # propagate exit status.
    4.25-    exit 1
    4.26-  fi
    4.27-  ensure mkdir -p "$_stash"
    4.28-  local _cc_url="${_url}/cc-install"
    4.29-  local _sbcl_url="${_url}/pack/sbcl.tar.zst"
    4.30-  local _rocksdb_url="${_url}/pack/rocksdb.tar.zst"
    4.31-  ensure download "$_sbcl_url" "${_stash}/sbcl.tar.zst" "$_arch"
    4.32-  ensure download "$_rocksdb_url" "${_stash}/rocksdb.tar.zst" "$_arch"
    4.33-  ensure download "$_cc_url" "${_stash}/cc-install" "$_arch"
    4.34-}
    4.35-
    4.36-say() {
    4.37-  printf 'install.sh: %s\n' "$1"
    4.38-}
    4.39-
    4.40-err() {
    4.41-  say "$1" >&2
    4.42-  exit 1
    4.43-}
    4.44-
    4.45-assert_nz() {
    4.46-  if [ -z "$1" ]; then err "assert_nz $2"; fi
    4.47-}
    4.48-
    4.49-check_cmd() {
    4.50-  command -v "$1" > /dev/null 2>&1
    4.51-}
    4.52-
    4.53-need_cmd() {
    4.54-  if ! check_cmd "$1"; then
    4.55-    err "need '$1' (command not found)"
    4.56-  fi
    4.57-}
    4.58-
    4.59-# Run a command that should never fail. If the command fails execution
    4.60-# will immediately terminate with an error showing the failing
    4.61-# command.
    4.62-ensure() {
    4.63-  if ! "$@"; then err "command failed: $*"; fi
    4.64-}
    4.65-
    4.66-# Check if curl supports the --retry flag, then pass it to the curl invocation.
    4.67-check_curl_for_retry_support() {
    4.68-  local _retry_supported=""
    4.69-  # "unspecified" is for arch, allows for possibility old OS using macports, homebrew, etc.
    4.70-  if check_help_for "notspecified" "curl" "--retry"; then
    4.71-    _retry_supported="--retry 3"
    4.72-    if check_help_for "notspecified" "curl" "--continue-at"; then
    4.73-      # "-C -" tells curl to automatically find where to resume the download when retrying.
    4.74-      _retry_supported="--retry 3 -C -"
    4.75-    fi
    4.76-  fi
    4.77-
    4.78-  RETVAL="$_retry_supported"
    4.79-}
    4.80-
    4.81-# Return cipher suite string specified by user, otherwise return strong TLS 1.2-1.3 cipher suites
    4.82-# if support by local tools is detected. Detection currently supports these curl backends:
    4.83-# GnuTLS and OpenSSL (possibly also LibreSSL and BoringSSL). Return value can be empty.
    4.84-get_ciphersuites_for_curl() {
    4.85-  if [ -n "${TLS_CIPHERSUITES-}" ]; then
    4.86-    # user specified custom cipher suites, assume they know what they're doing
    4.87-    RETVAL="$TLS_CIPHERSUITES"
    4.88-    return
    4.89-  fi
    4.90-
    4.91-  local _openssl_syntax="no"
    4.92-  local _gnutls_syntax="no"
    4.93-  local _backend_supported="yes"
    4.94-  if curl -V | grep -q ' OpenSSL/'; then
    4.95-    _openssl_syntax="yes"
    4.96-  elif curl -V | grep -iq ' LibreSSL/'; then
    4.97-    _openssl_syntax="yes"
    4.98-  elif curl -V | grep -iq ' BoringSSL/'; then
    4.99-    _openssl_syntax="yes"
   4.100-  elif curl -V | grep -iq ' GnuTLS/'; then
   4.101-    _gnutls_syntax="yes"
   4.102-  else
   4.103-    _backend_supported="no"
   4.104-  fi
   4.105-
   4.106-  local _args_supported="no"
   4.107-  if [ "$_backend_supported" = "yes" ]; then
   4.108-    # "unspecified" is for arch, allows for possibility old OS using macports, homebrew, etc.
   4.109-    if check_help_for "notspecified" "curl" "--tlsv1.2" "--ciphers" "--proto"; then
   4.110-      _args_supported="yes"
   4.111-    fi
   4.112-  fi
   4.113-
   4.114-  local _cs=""
   4.115-  if [ "$_args_supported" = "yes" ]; then
   4.116-    if [ "$_openssl_syntax" = "yes" ]; then
   4.117-      _cs=$(get_strong_ciphersuites_for "openssl")
   4.118-    elif [ "$_gnutls_syntax" = "yes" ]; then
   4.119-      _cs=$(get_strong_ciphersuites_for "gnutls")
   4.120-    fi
   4.121-  fi
   4.122-
   4.123-  RETVAL="$_cs"
   4.124-}
   4.125-
   4.126-# Return cipher suite string specified by user, otherwise return strong TLS 1.2-1.3 cipher suites
   4.127-# if support by local tools is detected. Detection currently supports these wget backends:
   4.128-# GnuTLS and OpenSSL (possibly also LibreSSL and BoringSSL). Return value can be empty.
   4.129-get_ciphersuites_for_wget() {
   4.130-  if [ -n "${TLS_CIPHERSUITES-}" ]; then
   4.131-    # user specified custom cipher suites, assume they know what they're doing
   4.132-    RETVAL="$TLS_CIPHERSUITES"
   4.133-    return
   4.134-  fi
   4.135-
   4.136-  local _cs=""
   4.137-  if wget -V | grep -q '\-DHAVE_LIBSSL'; then
   4.138-    # "unspecified" is for arch, allows for possibility old OS using macports, homebrew, etc.
   4.139-    if check_help_for "notspecified" "wget" "TLSv1_2" "--ciphers" "--https-only" "--secure-protocol"; then
   4.140-      _cs=$(get_strong_ciphersuites_for "openssl")
   4.141-    fi
   4.142-  elif wget -V | grep -q '\-DHAVE_LIBGNUTLS'; then
   4.143-    # "unspecified" is for arch, allows for possibility old OS using macports, homebrew, etc.
   4.144-    if check_help_for "notspecified" "wget" "TLSv1_2" "--ciphers" "--https-only" "--secure-protocol"; then
   4.145-      _cs=$(get_strong_ciphersuites_for "gnutls")
   4.146-    fi
   4.147-  fi
   4.148-
   4.149-  RETVAL="$_cs"
   4.150-}
   4.151-
   4.152-check_help_for() {
   4.153-    local _arch
   4.154-    local _cmd
   4.155-    local _arg
   4.156-    _arch="$1"
   4.157-    shift
   4.158-    _cmd="$1"
   4.159-    shift
   4.160-
   4.161-    local _category
   4.162-    if "$_cmd" --help | grep -q 'For all options use the manual or "--help all".'; then
   4.163-      _category="all"
   4.164-    else
   4.165-      _category=""
   4.166-    fi
   4.167-
   4.168-    case "$_arch" in
   4.169-
   4.170-        *darwin*)
   4.171-        if check_cmd sw_vers; then
   4.172-            case $(sw_vers -productVersion) in
   4.173-                10.*)
   4.174-                    # If we're running on macOS, older than 10.13, then we always
   4.175-                    # fail to find these options to force fallback
   4.176-                    if [ "$(sw_vers -productVersion | cut -d. -f2)" -lt 13 ]; then
   4.177-                        # Older than 10.13
   4.178-                        echo "Warning: Detected macOS platform older than 10.13"
   4.179-                        return 1
   4.180-                    fi
   4.181-                    ;;
   4.182-                11.*)
   4.183-                    # We assume Big Sur will be OK for now
   4.184-                    ;;
   4.185-                *)
   4.186-                    # Unknown product version, warn and continue
   4.187-                    echo "Warning: Detected unknown macOS major version: $(sw_vers -productVersion)"
   4.188-                    echo "Warning TLS capabilities detection may fail"
   4.189-                    ;;
   4.190-            esac
   4.191-        fi
   4.192-        ;;
   4.193-
   4.194-    esac
   4.195-
   4.196-    for _arg in "$@"; do
   4.197-        if ! "$_cmd" --help "$_category" | grep -q -- "$_arg"; then
   4.198-            return 1
   4.199-        fi
   4.200-    done
   4.201-
   4.202-    true # not strictly needed
   4.203-}
   4.204-
   4.205-# Return strong TLS 1.2-1.3 cipher suites in OpenSSL or GnuTLS syntax. TLS 1.2
   4.206-# excludes non-ECDHE and non-AEAD cipher suites. DHE is excluded due to bad
   4.207-# DH params often found on servers (see RFC 7919). Sequence matches or is
   4.208-# similar to Firefox 68 ESR with weak cipher suites disabled via about:config.
   4.209-# $1 must be openssl or gnutls.
   4.210-get_strong_ciphersuites_for() {
   4.211-  if [ "$1" = "openssl" ]; then
   4.212-    # OpenSSL is forgiving of unknown values, no problems with TLS 1.3 values on versions that don't support it yet.
   4.213-    echo "TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384"
   4.214-  elif [ "$1" = "gnutls" ]; then
   4.215-    # GnuTLS isn't forgiving of unknown values, so this may require a GnuTLS version that supports TLS 1.3 even if wget doesn't.
   4.216-    # Begin with SECURE128 (and higher) then remove/add to build cipher suites. Produces same 9 cipher suites as OpenSSL but in slightly different order.
   4.217-    echo "SECURE128:-VERS-SSL3.0:-VERS-TLS1.0:-VERS-TLS1.1:-VERS-DTLS-ALL:-CIPHER-ALL:-MAC-ALL:-KX-ALL:+AEAD:+ECDHE-ECDSA:+ECDHE-RSA:+AES-128-GCM:+CHACHA20-POLY1305:+AES-256-GCM"
   4.218-  fi
   4.219-}
   4.220-
   4.221-check_proc() {
   4.222-  # Check for /proc by looking for the /proc/self/exe link
   4.223-  # This is only run on Linux
   4.224-  if ! test -L /proc/self/exe ; then
   4.225-    err "fatal: Unable to find /proc/self/exe.  Is /proc mounted?  Installation cannot proceed without /proc."
   4.226-  fi
   4.227-}
   4.228-
   4.229-get_bitness() {
   4.230-  need_cmd head
   4.231-  # Architecture detection without dependencies beyond coreutils.
   4.232-  # ELF files start out "\x7fELF", and the following byte is
   4.233-  #   0x01 for 32-bit and
   4.234-  #   0x02 for 64-bit.
   4.235-  # The printf builtin on some shells like dash only supports octal
   4.236-  # escape sequences, so we use those.
   4.237-  local _current_exe_head
   4.238-  _current_exe_head=$(head -c 5 /proc/self/exe )
   4.239-  if [ "$_current_exe_head" = "$(printf '\177ELF\001')" ]; then
   4.240-    echo 32
   4.241-  elif [ "$_current_exe_head" = "$(printf '\177ELF\002')" ]; then
   4.242-    echo 64
   4.243-  else
   4.244-    err "unknown platform bitness"
   4.245-  fi
   4.246-}
   4.247-
   4.248-is_host_amd64_elf() {
   4.249-  need_cmd head
   4.250-  need_cmd tail
   4.251-  # ELF e_machine detection without dependencies beyond coreutils.
   4.252-  # Two-byte field at offset 0x12 indicates the CPU,
   4.253-  # but we're interested in it being 0x3E to indicate amd64, or not that.
   4.254-  local _current_exe_machine
   4.255-  _current_exe_machine=$(head -c 19 /proc/self/exe | tail -c 1)
   4.256-  [ "$_current_exe_machine" = "$(printf '\076')" ]
   4.257-}
   4.258-
   4.259-get_endianness() {
   4.260-  local cputype=$1
   4.261-  local suffix_eb=$2
   4.262-  local suffix_el=$3
   4.263-
   4.264-  # detect endianness without od/hexdump, like get_bitness() does.
   4.265-  need_cmd head
   4.266-  need_cmd tail
   4.267-
   4.268-  local _current_exe_endianness
   4.269-  _current_exe_endianness="$(head -c 6 /proc/self/exe | tail -c 1)"
   4.270-  if [ "$_current_exe_endianness" = "$(printf '\001')" ]; then
   4.271-    echo "${cputype}${suffix_el}"
   4.272-  elif [ "$_current_exe_endianness" = "$(printf '\002')" ]; then
   4.273-    echo "${cputype}${suffix_eb}"
   4.274-  else
   4.275-    err "unknown platform endianness"
   4.276-  fi
   4.277-}
   4.278-
   4.279-get_architecture() {
   4.280-  local _ostype _cputype _bitness _arch _clibtype
   4.281-  _ostype="$(uname -s)"
   4.282-  _cputype="$(uname -m)"
   4.283-  _clibtype="gnu"
   4.284-
   4.285-  if [ "$_ostype" = Linux ]; then
   4.286-    if [ "$(uname -o)" = Android ]; then
   4.287-      _ostype=Android
   4.288-    fi
   4.289-    if ldd --version 2>&1 | grep -q 'musl'; then
   4.290-      _clibtype="musl"
   4.291-    fi
   4.292-  fi
   4.293-
   4.294-  if [ "$_ostype" = Darwin ] && [ "$_cputype" = i386 ]; then
   4.295-    # Darwin `uname -m` lies
   4.296-    if sysctl hw.optional.x86_64 | grep -q ': 1'; then
   4.297-      _cputype=x86_64
   4.298-    fi
   4.299-  fi
   4.300-
   4.301-  if [ "$_ostype" = SunOS ]; then
   4.302-    # Both Solaris and illumos presently announce as "SunOS" in "uname -s"
   4.303-    # so use "uname -o" to disambiguate.  We use the full path to the
   4.304-    # system uname in case the user has coreutils uname first in PATH,
   4.305-    # which has historically sometimes printed the wrong value here.
   4.306-    if [ "$(/usr/bin/uname -o)" = illumos ]; then
   4.307-      _ostype=illumos
   4.308-    fi
   4.309-
   4.310-    # illumos systems have multi-arch userlands, and "uname -m" reports the
   4.311-    # machine hardware name; e.g., "i86pc" on both 32- and 64-bit x86
   4.312-    # systems.  Check for the native (widest) instruction set on the
   4.313-    # running kernel:
   4.314-    if [ "$_cputype" = i86pc ]; then
   4.315-      _cputype="$(isainfo -n)"
   4.316-    fi
   4.317-  fi
   4.318-
   4.319-  case "$_ostype" in
   4.320-
   4.321-    Android)
   4.322-      _ostype=linux-android
   4.323-      ;;
   4.324-
   4.325-    Linux)
   4.326-      check_proc
   4.327-      _ostype=unknown-linux-$_clibtype
   4.328-      _bitness=$(get_bitness)
   4.329-      ;;
   4.330-
   4.331-    FreeBSD)
   4.332-      _ostype=unknown-freebsd
   4.333-      ;;
   4.334-
   4.335-    NetBSD)
   4.336-      _ostype=unknown-netbsd
   4.337-      ;;
   4.338-
   4.339-    DragonFly)
   4.340-      _ostype=unknown-dragonfly
   4.341-      ;;
   4.342-
   4.343-    Darwin)
   4.344-      _ostype=apple-darwin
   4.345-      ;;
   4.346-
   4.347-    illumos)
   4.348-      _ostype=unknown-illumos
   4.349-      ;;
   4.350-
   4.351-    MINGW* | MSYS* | CYGWIN* | Windows_NT)
   4.352-      _ostype=pc-windows-gnu
   4.353-      ;;
   4.354-
   4.355-    *)
   4.356-      err "unrecognized OS type: $_ostype"
   4.357-      ;;
   4.358-
   4.359-  esac
   4.360-
   4.361-  case "$_cputype" in
   4.362-
   4.363-    i386 | i486 | i686 | i786 | x86)
   4.364-      _cputype=i686
   4.365-      ;;
   4.366-
   4.367-    xscale | arm)
   4.368-      _cputype=arm
   4.369-      if [ "$_ostype" = "linux-android" ]; then
   4.370-        _ostype=linux-androideabi
   4.371-      fi
   4.372-      ;;
   4.373-
   4.374-    armv6l)
   4.375-      _cputype=arm
   4.376-      if [ "$_ostype" = "linux-android" ]; then
   4.377-        _ostype=linux-androideabi
   4.378-      else
   4.379-        _ostype="${_ostype}eabihf"
   4.380-      fi
   4.381-      ;;
   4.382-
   4.383-    armv7l | armv8l)
   4.384-      _cputype=armv7
   4.385-      if [ "$_ostype" = "linux-android" ]; then
   4.386-        _ostype=linux-androideabi
   4.387-      else
   4.388-        _ostype="${_ostype}eabihf"
   4.389-      fi
   4.390-      ;;
   4.391-
   4.392-    aarch64 | arm64)
   4.393-      _cputype=aarch64
   4.394-      ;;
   4.395-
   4.396-    x86_64 | x86-64 | x64 | amd64)
   4.397-      _cputype=x86_64
   4.398-      ;;
   4.399-
   4.400-    mips)
   4.401-      _cputype=$(get_endianness mips '' el)
   4.402-      ;;
   4.403-
   4.404-    mips64)
   4.405-      if [ "$_bitness" -eq 64 ]; then
   4.406-        # only n64 ABI is supported for now
   4.407-        _ostype="${_ostype}abi64"
   4.408-        _cputype=$(get_endianness mips64 '' el)
   4.409-      fi
   4.410-      ;;
   4.411-
   4.412-    ppc)
   4.413-      _cputype=powerpc
   4.414-      ;;
   4.415-
   4.416-    ppc64)
   4.417-      _cputype=powerpc64
   4.418-      ;;
   4.419-
   4.420-    ppc64le)
   4.421-      _cputype=powerpc64le
   4.422-      ;;
   4.423-
   4.424-    s390x)
   4.425-      _cputype=s390x
   4.426-      ;;
   4.427-    riscv64)
   4.428-      _cputype=riscv64gc
   4.429-      ;;
   4.430-    loongarch64)
   4.431-      _cputype=loongarch64
   4.432-      ;;
   4.433-    *)
   4.434-      err "unknown CPU type: $_cputype"
   4.435-
   4.436-  esac
   4.437-
   4.438-  # Detect 64-bit linux with 32-bit userland
   4.439-  if [ "${_ostype}" = unknown-linux-gnu ] && [ "${_bitness}" -eq 32 ]; then
   4.440-    case $_cputype in
   4.441-      x86_64)
   4.442-        if [ -n "${CPUTYPE:-}" ]; then
   4.443-          _cputype="$CPUTYPE"
   4.444-        else {
   4.445-          # 32-bit executable for amd64 = x32
   4.446-          if is_host_amd64_elf; then {
   4.447-            echo "This host is running an x32 userland; as it stands, x32 support is poor," 1>&2
   4.448-            echo "and there isn't a native toolchain -- you will have to install" 1>&2
   4.449-            echo "multiarch compatibility with i686 and/or amd64, then select one" 1>&2
   4.450-            echo "by re-running this script with the CPUTYPE environment variable" 1>&2
   4.451-            echo "set to i686 or x86_64, respectively." 1>&2
   4.452-            exit 1
   4.453-          }; else
   4.454-            _cputype=i686
   4.455-          fi
   4.456-        }; fi
   4.457-        ;;
   4.458-      mips64)
   4.459-        _cputype=$(get_endianness mips '' el)
   4.460-        ;;
   4.461-      powerpc64)
   4.462-        _cputype=powerpc
   4.463-        ;;
   4.464-      aarch64)
   4.465-        _cputype=armv7
   4.466-        if [ "$_ostype" = "linux-android" ]; then
   4.467-          _ostype=linux-androideabi
   4.468-        else
   4.469-          _ostype="${_ostype}eabihf"
   4.470-        fi
   4.471-        ;;
   4.472-      riscv64gc)
   4.473-        err "riscv64 with 32-bit userland unsupported"
   4.474-        ;;
   4.475-    esac
   4.476-  fi
   4.477-
   4.478-  if [ "$_ostype" = "unknown-linux-gnueabihf" ] && [ "$_cputype" = armv7 ]; then
   4.479-    if ensure grep '^Features' /proc/cpuinfo | grep -q -v neon; then
   4.480-      # At least one processor does not have NEON.
   4.481-      _cputype=arm
   4.482-    fi
   4.483-  fi
   4.484-
   4.485-  _arch="${_cputype}-${_ostype}"
   4.486-
   4.487-  RETVAL="$_arch"
   4.488-}
   4.489-
   4.490-# This wraps curl or wget. Try curl first, if not installed,
   4.491-# use wget instead.
   4.492-download() {
   4.493-  local _dld
   4.494-  local _ciphersuites
   4.495-  local _err
   4.496-  local _status
   4.497-  local _retry
   4.498-  if check_cmd curl; then
   4.499-    _dld=curl
   4.500-  elif check_cmd wget; then
   4.501-    _dld=wget
   4.502-  else
   4.503-    _dld='curl or wget' # to be used in error message of need_cmd
   4.504-  fi
   4.505-
   4.506-  if [ "$1" = --check ]; then
   4.507-    need_cmd "$_dld"
   4.508-  elif [ "$_dld" = curl ]; then
   4.509-    check_curl_for_retry_support
   4.510-    _retry="$RETVAL"
   4.511-    get_ciphersuites_for_curl
   4.512-    _ciphersuites="$RETVAL"
   4.513-    if [ -n "$_ciphersuites" ]; then
   4.514-      _err=$(curl $_retry --proto '=https' --tlsv1.2 --ciphers "$_ciphersuites" --silent --show-error --fail --location "$1" --output "$2" 2>&1)
   4.515-      _status=$?
   4.516-    else
   4.517-      echo "Warning: Not enforcing strong cipher suites for TLS, this is potentially less secure"
   4.518-      if ! check_help_for "$3" curl --proto --tlsv1.2; then
   4.519-        echo "Warning: Not enforcing TLS v1.2, this is potentially less secure"
   4.520-        _err=$(curl $_retry --silent --show-error --fail --location "$1" --output "$2" 2>&1)
   4.521-        _status=$?
   4.522-      else
   4.523-        _err=$(curl $_retry --proto '=https' --tlsv1.2 --silent --show-error --fail --location "$1" --output "$2" 2>&1)
   4.524-        _status=$?
   4.525-      fi
   4.526-    fi
   4.527-    if [ -n "$_err" ]; then
   4.528-      echo "$_err" >&2
   4.529-      if echo "$_err" | grep -q 404$; then
   4.530-        err "installer for platform '$3' not found, this may be unsupported"
   4.531-      fi
   4.532-    fi
   4.533-    return $_status
   4.534-  elif [ "$_dld" = wget ]; then
   4.535-    if [ "$(wget -V 2>&1|head -2|tail -1|cut -f1 -d" ")" = "BusyBox" ]; then
   4.536-      echo "Warning: using the BusyBox version of wget.  Not enforcing strong cipher suites for TLS or TLS v1.2, this is potentially less secure"
   4.537-      _err=$(wget "$1" -O "$2" 2>&1)
   4.538-      _status=$?
   4.539-    else
   4.540-      get_ciphersuites_for_wget
   4.541-      _ciphersuites="$RETVAL"
   4.542-      if [ -n "$_ciphersuites" ]; then
   4.543-        _err=$(wget --https-only --secure-protocol=TLSv1_2 --ciphers "$_ciphersuites" "$1" -O "$2" 2>&1)
   4.544-        _status=$?
   4.545-      else
   4.546-        echo "Warning: Not enforcing strong cipher suites for TLS, this is potentially less secure"
   4.547-        if ! check_help_for "$3" wget --https-only --secure-protocol; then
   4.548-          echo "Warning: Not enforcing TLS v1.2, this is potentially less secure"
   4.549-          _err=$(wget "$1" -O "$2" 2>&1)
   4.550-          _status=$?
   4.551-        else
   4.552-          _err=$(wget --https-only --secure-protocol=TLSv1_2 "$1" -O "$2" 2>&1)
   4.553-          _status=$?
   4.554-        fi
   4.555-      fi
   4.556-    fi
   4.557-    if [ -n "$_err" ]; then
   4.558-      echo "$_err" >&2
   4.559-      if echo "$_err" | grep -q ' 404 Not Found$'; then
   4.560-        err "installer for platform '$3' not found, this may be unsupported"
   4.561-      fi
   4.562-    fi
   4.563-    return $_status
   4.564-  else
   4.565-    err "Unknown downloader"   # should not reach here
   4.566-  fi
   4.567-}
   4.568-
   4.569-main "$@" || exit 1