#!/usr/bin/env bash set -e setup_version='v1.2024.01.12' # # Usage: # # * To install run # wget https://git.io/digital-cinema-tools-setup && bash digital-cinema-tools-setup # in a terminal # # # * For updates or re-runs run # digital-cinema-tools-setup # in a terminal # # This setup script will install everything required (batteries included) to run # # * dcp_inspect: Inspect and validate digital cinema packages (DCPs) # See https://github.com/wolfgangw/backports#readme # # and a number of other digital cinema-related tools: # # * db_adjust_for_dolby_fader_ref.rb: Calculate adjustments for Dolby CP650/750 7.0 setting # * dc_crypto_context.rb: Check certificate chains for digital cinema compliance # * decrypt_kdm.rb: Decrypt Interop/SMPTE KDMs # * make-dc-certificate-chain.rb: Generate an example digital cinema compliant certificate chain # * public_key_thumbprint.rb: Compute dnQualifier/public key thumbprint of a X.509 certificate # * signature_check.rb: Check XML signatures of DCP infrastructure documents # * x509_extract.rb: Extract X.509 certificates from digital cinema documents # * x509_inspect.rb: Inspect X.509 certificates # * xsd-check.rb: Validate XML documents against Schema definitions # # This installer supports Debian / Ubuntu / Fedora / MacOS # Needs a working network connection # # It tries hard not to break anything and to respect the existing environment. # You can run it multiple times, should anything go wrong during a setup run (network problems etc.) # # Wolfgang Woehl 2012-2023 # # # Location of self # setup_dirname=$( cd "$(dirname "${BASH_SOURCE[0]}")" && pwd ) setup_basename=$(basename ${BASH_SOURCE[0]}) setup_fullpath="$setup_dirname/$setup_basename" echo "$setup_basename $setup_version" bashrc=$HOME/.bashrc inputrc=$HOME/.inputrc script_runner=$(whoami) basedir=$HOME/.digital_cinema_tools libdir=$basedir/.lib bindir=$basedir/.bin # Ruby version management: rbenv rbenv_url="https://github.com/sstephenson/rbenv.git" export RBENV_ROOT=$libdir/.rbenv rbenv_dir=$RBENV_ROOT rbenv_plugins_dir=$rbenv_dir/plugins # Ruby build system: ruby-build rubybuild_url="https://github.com/sstephenson/ruby-build.git" rubybuild_dir=$rbenv_plugins_dir/ruby-build ruby_version='3.2.2' gemrc=$HOME/.gemrc # Handle SMPTE and Interop trackfiles: AS-DCP Lib asdcplib_url="https://github.com/cinecert/asdcplib.git" asdcplib_version='2.12.3' asdcplib_version_tag='rel_2_12_3' asdcplib_dir=$libdir/asdcplib asdcplib_build_dir="$asdcplib_dir/build" asdcplib_install_dir=$bindir/asdcplib # Digital cinema tools distribution: dist_url="https://github.com/wolfgangw/digital_cinema_tools_distribution.git" dist_dir=$libdir/digital_cinema_tools_distribution errors=() exec_shell_required=false command_exists() { type "$1" &> /dev/null } location_exists() { [ -e "$1" ] } string_includes() { [[ "$1" =~ "$2" ]] } echo_last() { local arr=("${!1}") echo ${arr[${#arr[@]}-1]} } remove_if_exists() { if location_exists $1 then rm -rf $1 fi } location_is_git_repo() { location_exists "$1" && location_exists "$1/.git" && [ -d "$1/.git" ] } # Only linux systems in mind for now if [[ $MACHTYPE =~ linux || $MACHTYPE =~ darwin ]] then echo "Platform: $MACHTYPE supported" else echo "Platform: This installer supports only linux and darwin systems" exit 1 fi # Check and bail out if the installer is run with root privileges if [ $script_runner == "root" ] then echo echo 'Do not run this installer as root' echo 'Do not run this installer via sudo' echo 'This installer will ask for privileges if and when required' echo echo 'That said:' echo echo 'If you know exactly why you would want to' echo "continue as root -- usually you don't want to --" read -p 'then type root and press [ENTER]: ' run_as_root_confirm if ! [ "$run_as_root_confirm" == "root" ] then exit 1 fi echo 'Continuing as root ...' sleep 3 fi # # Which OS distribution are we on? # if [ -f /etc/os-release ] && grep 'Debian' /etc/os-release &> /dev/null then os_dist=debian elif [ -f /etc/fedora-release ] then os_dist=redhat elif [ -f /etc/redhat-release ] then os_dist=redhat elif [ -f /etc/lsb-release ] && grep 'Ubuntu' /etc/lsb-release &> /dev/null then os_dist=ubuntu elif [ -f /etc/lsb-release ] && grep 'LinuxMint' /etc/lsb-release &> /dev/null then os_dist=ubuntu elif [ -f /etc/lsb-release ] && grep 'Pop!_OS' /etc/lsb-release &> /dev/null then os_dist=ubuntu elif command_exists lsb_release then # do the debian thing here lsb_release -a, -i, -r ... if [[ "$(lsb_release --id)" =~ Debian ]] then os_dist=debian fi elif command_exists sw_vers then # do the mac thing if [[ "$(sw_vers)" =~ macOS ]] then os_dist=macos fi fi # Bail out if non-supported OS distribution if ! [ -z $os_dist ] then echo "OS: $os_dist" else echo 'OS not supported' exit 1 fi # Bail out if we don't have sudo if command_exists sudo then case $os_dist in debian) if echo `groups` | grep sudo &>/dev/null then echo "$os_dist: sudo OK" else echo "$os_dist: sudo: Need to be member of the sudo group." echo echo 'Run the following 3 commands:' echo echo "su - # will prompt for your root password" echo "adduser `whoami` sudo # Adds you to the sudo group" echo 'exit # exits from root account' echo echo 'Then log out or reboot' echo 'Then re-run digital-cinema-tools-setup' echo exit 1 fi ;; macos) echo "$os_dist: sudo not required" esac else echo 'Required command "sudo" not found. Please install sudo' exit 1 fi # Depending on which OS we're on set the required packager and switches # to install a basic set of packages from distribution sources case $os_dist in debian|ubuntu) query='dpkg-query' query_params='-s' packager='apt-get' packager_params='-y install' # build-essential odd .. packages_required=( autoconf patch build-essential rustc libssl-dev libyaml-dev libreadline-dev zlib1g-dev libgmp-dev libncurses5-dev libffi-dev libgdbm6 libgdbm-dev libdb-dev uuid-dev cmake curl libxerces-c-dev xmlsec1 libreadline-dev libssl-dev sox git libffi-dev fd-find ) packager_prep="$packager update" ;; redhat) query='rpm' query_params='--query' packager='yum' packager_params='-y install' packages_required=( make automake autoconf cmake gcc gcc-c++ rustc wget xerces-c-devel xmlsec1 xmlsec1-openssl libyaml-devel readline-devel zlib-devel libgmp-devel libncurses5-devel libgdbm6 libgdbm6-devel uuid-devel openssl-devel sox git libffi-devel fd-find ) packager_prep="$packager update" # erm, FIXME ;; macos) query='brew' query_params='list' packager='brew' packager_params='install' packages_required=( cmake git xerces-c openssl@3 gmp libyaml readline rust sox fd ) packager_prep="$packager update" esac # Check for the presence of required basic distribution packages if command_exists $query && command_exists $packager then packages_missing=() for package in ${packages_required[@]} do if $query $query_params $package &> /dev/null then echo "$package: OK" else echo "$package: Installation required" packages_missing+=($package) fi done if [ ${#packages_missing[@]} -gt 0 ] then echo echo "$setup_basename: ${#packages_missing[@]} packages missing" echo "$setup_basename: ${packages_missing[@]}" echo case $os_dist in debian|ubuntu) echo "Please enter your password" ;; redhat) echo 'Please enter your root password' ;; esac # Install packages case $os_dist in debian|ubuntu|redhat) if ! [ -z "$packager_prep" ] then if ! sudo $packager_prep then errors+=("$setup_basename: Failed to prepare package installation") && echo_last errors[@] else echo "$setup_basename: Package preparation OK" fi fi if ! sudo $packager $packager_params "${packages_missing[@]}" then errors+=("$packager: Failed to install basic requirements") && echo_last errors[@] sudo -K # drop sudo privileges exit 1 else echo "$packager: OK" fi sudo -K ;; macos) if ! [ -z "$packager_prep" ] then if ! $packager_prep then errors+=("$setup_basename: Failed to prepare package installation") && echo_last errors[@] else echo "$setup_basename: Package preparation OK" fi fi if ! $packager $packager_params "${packages_missing[@]}" then errors+=("$packager: Failed to install basic requirements") && echo_last errors[@] exit 1 else echo "$packager: OK" fi ;; esac fi else errors+=("$setup_basename: Required packager tools not found: $query/$packager. Exiting") && echo_last errors[@] exit 1 fi # Set up directories for digital cinema tools if ! location_exists $basedir ; then mkdir $basedir ; fi if ! location_exists $libdir ; then mkdir $libdir ; fi if ! location_exists $bindir ; then mkdir $bindir ; fi # Check for $bindir and inclusion in PATH if string_includes $PATH "$bindir" then echo "PATH: $bindir available in PATH" fi if grep "export PATH=$bindir:" $bashrc then echo "bashrc: $bindir already included. OK" else echo "bashrc: Adding $bindir to PATH" echo '' >> $bashrc echo "# $setup_basename: Add $bindir to PATH" >> $bashrc echo "export PATH=$bindir:"'$PATH' >> $bashrc source $bashrc exec_shell_required=true fi # rbenv if command_exists rvm then echo echo "Sorry. This installer insists on using rbenv for Ruby version management." echo "You have RVM installed and those 2 won't co-exist peacefully, so there." echo "If you want to continue remove RVM from your system and re-run this installer." echo "Apologies for the obtrusive hassle." echo exit 1 fi if command_exists rbenv then echo "rbenv: OK" else if location_exists $rbenv_dir && location_is_git_repo $rbenv_dir then echo "rbenv: Repository exists" cd $rbenv_dir if ! git pull then errors+=("rbenv: Failed to pull updates") && echo_last errors[@] fi if string_includes $PATH "$rbenv_dir/bin" then echo "rbenv: PATH includes rbenv bin dir" else errors+=("rbenv: PATH does not include rbenv bin dir") && echo_last errors[@] fi else echo "rbenv: Installing" remove_if_exists $rbenv_dir if ! git clone $rbenv_url $rbenv_dir then errors+=("rbenv: Failed to clone repository. Try again later") && echo_last errors[@] fi echo '' >> $bashrc echo "# $setup_basename: rbenv environment" >> $bashrc echo "export RBENV_ROOT=$rbenv_dir" >> $bashrc echo "export PATH=$rbenv_dir/bin:"'$PATH' >> $bashrc echo 'eval "$(rbenv init -)"' >> $bashrc RBENV_ROOT=$rbenv_dir PATH=$rbenv_dir/bin:$PATH eval "$(rbenv init -)" exec_shell_required=true if command_exists rbenv then echo "rbenv: OK" else echo "rbenv: Command 'rbenv' not found" exit 1 fi fi fi # gems: ri/rdoc switches if [ -e $gemrc ] then if grep '^gem: --no-ri --no-rdoc' $gemrc then echo 'gemrc: OK' else echo 'gemrc: Keeping changed gemrc (--no-ri/rdoc switches will not be added)' fi else echo 'gem: --no-ri --no-rdoc' > $gemrc fi # ruby-build (as rbenv plugin) if location_exists $rbenv_dir then if ! location_exists $rbenv_plugins_dir then mkdir $rbenv_plugins_dir fi else mkdir -p $rbenv_plugins_dir # eh? FIXME fi cd $rbenv_plugins_dir if location_is_git_repo $rubybuild_dir then cd $rubybuild_dir if ! git pull origin master then errors+=("ruby-build: Failed to pull updates. Try again later") && echo_last errors[@] else echo 'ruby-build: OK' fi else remove_if_exists $rubybuild_dir echo 'ruby-build: Installing' if ! git clone $rubybuild_url then errors+=("ruby-build: Failed to clone repository. Try again later") && echo_last errors[@] else echo 'ruby-build: OK' fi fi # Try to install a ruby version # Explicitly set global $ruby_version if command_exists rbenv then if ! rbenv global $ruby_version then echo 'rbenv: Required ruby not installed' fi if [[ `rbenv version` =~ $ruby_version ]] && command_exists ruby then echo "Ruby: OK" else echo "Ruby: Installing ... This will take a while" if ! CONFIGURE_OPTS="--disable-install-doc" MAKE_OPTS="-j4" rbenv install $ruby_version --verbose then errors+=("Ruby: Failed to install requested version") && echo_last errors[@] else rbenv global $ruby_version rbenv rehash echo "Ruby: $( rbenv version )" echo 'Ruby: OK' fi fi else errors+=("Ruby: Failed to install ruby (Required command rbenv not found)") && echo_last errors[@] fi # Nokogiri (with c14n) if command_exists gem then if gem list -i nokogiri &> /dev/null then echo 'Nokogiri: Found installed gem' else # Install Nokogiri gem if ! gem install nokogiri then errors+=("Nokogiri: Failed to install required gem nokogiri") && echo_last errors[@] else rbenv rehash echo 'Nokogiri: Installed gem nokogiri' fi fi # Check for C14N support if gem list -i nokogiri &> /dev/null then if [[ `rbenv version` =~ $ruby_version ]] && command_exists ruby then ruby -e "require 'rubygems'; require 'nokogiri'; if Nokogiri::XML::Document.new.respond_to?( 'canonicalize' ) then exit 0 else exit 1 ; end" if [ $? == 0 ] then nokogiri_c14n=true echo 'Nokogiri: C14N support present' else nokogiri_c14n=false errors+=("Nokogiri: Installed version does not support C14N") && echo_last errors[@] fi else errors+=("Nokogiri: Could not test Nokogiri C14N support (Required ruby version not found)") && echo_last errors[@] fi if $nokogiri_c14n then echo 'Nokogiri: OK' else errors+=("Nokogiri: There is a problem with the installed version of Nokogiri. Consider removing your installed version of Nokogiri and re-run this installer") && echo_last errors[@] fi fi else errors+=("Nokogiri: Failed to install Nokogiri (Required command gem not found)") && echo_last errors[@] fi # Nokogiri # asdcplib cd $libdir if command_exists asdcp-info && command_exists asdcp-unwrap && command_exists kmuuidgen && [[ `asdcp-info -V` =~ $asdcplib_version ]] then echo "asdcplib: OK ($asdcplib_version)" if location_exists $asdcplib_dir && location_is_git_repo $asdcplib_dir then cd $asdcplib_dir git checkout master if ! git pull then errors+=("asdcplib: Failed to pull updates") && echo_last errors[@] fi else echo "asdcplib: Is installed but repo $asdcplib_dir not found. Not changing anything" fi else echo "asdcplib: Installing $asdcplib_version ..." remove_if_exists $asdcplib_dir mkdir $asdcplib_dir && cd $asdcplib_dir if ! git clone $asdcplib_url $asdcplib_dir then errors+=("asdcplib: Failed to clone repository") && echo_last errors[@] else git checkout $asdcplib_version_tag mkdir $asdcplib_build_dir && cd $asdcplib_build_dir case $os_dist in ubuntu) export LDFLAGS="-L/usr/lib/$(dpkg-architecture -qDEB_HOST_MULTIARCH)" ;; redhat) export LDFLAGS='' ;; macos) echo "asdcplib ($os_dist): FIXME patching CMakeLists.txt" sed -i '' -e 's/cmake_minimum_required(VERSION 2.8.12)/cmake_minimum_required(VERSION 3.0)/' ../CMakeLists.txt esac if cmake -DCMAKE_INSTALL_PREFIX=$asdcplib_install_dir .. && make -j4 && make install then asdcplib_build=ok else asdcplib_build=fail errors+=("asdcplib: Can not create build directory") && echo_last errors[@] fi if [ "$asdcplib_build" = 'ok' ] then cd $bindir for tool in $asdcplib_install_dir/bin/* do if [ -e $bindir/$(basename ${tool}) ] then rm $bindir/$(basename ${tool}) echo "asdcplib: Updating $(basename ${tool})" ln -s $tool . else echo "asdcplib: Add to $bindir: $(basename ${tool})" ln -s $tool . fi done # asdcplib else errors+=("asdcplib: Building asdcplib failed") && echo_last errors[@] fi fi fi # asdcplib installed or built # Digital Cinema Tools distribution cd $libdir if location_is_git_repo $dist_dir then cd $dist_dir echo "Digital cinema tools distribution: Pulling updates ..." if ! git pull origin master then errors+=("Digital cinema tools distribution: Failed to pull updates. Try again later") && echo_last errors[@] fi else remove_if_exists $dist_dir if ! git clone $dist_url then errors+=("Digital cinema tools distribution: Failed to clone repository. Try again later") && echo_last errors[@] else echo 'Digital cinema tools distribution: Repository OK' fi fi # Update $bindir entries for distribution if location_exists $dist_dir then cd $dist_dir tools=( $( cat toollist ) ) cd $bindir for tool in ${tools[@]} do if [ -e $bindir/$tool ] && command_exists $tool then # Special case: setup might be hanging around here from a previous run: # When distribution setup would have failed and the downloaded setup been moved to $bindir. # Replace with repo version if [[ $tool =~ $setup_basename ]] && [ ! -L $setup_fullpath ] then echo "Digital cinema tools distribution: Replacing setup with repo version" rm $bindir/$tool ln -s $dist_dir/$tool . else echo "Digital cinema tools distribution: $tool OK" fi else echo "Digital cinema tools distribution: Add to $bindir: $tool" ln -s $dist_dir/$tool . fi done else errors+=("Digital cinema tools distribution: Failed to update $bindir. Repository missing") && echo_last errors[@] fi # dcp_inspect: gem ttfunk if command_exists gem then if gem list -i ttfunk &> /dev/null then echo 'dcp_inspect: gem ttfunk OK' else if ! gem install ttfunk && rbenv rehash then echo 'dcp_inspect: Failed to install gem ttfunk' else echo 'dcp_inspect: gem ttfunk OK' fi fi fi # Done: Digital Cinemas Tools Distribution # Fastpath for tab-completion if [ -e $inputrc ] then # Leave any existing setting untouched if grep "^set show-all-if-ambiguous on$" $inputrc then echo 'Tab completion: Fastpath set to on. Leaving untouched. OK' elif grep "^set show-all-if-ambiguous off$" $inputrc then echo 'Tab completion: Fastpath set to off. Leaving untouched. OK' fi else touch $inputrc echo 'Tab completion: Setting fastpath to on' echo "# $setup_basename: This will make completions show up after 1 TAB hit" >> $inputrc echo 'set show-all-if-ambiguous on' >> $inputrc exec_shell_required=true fi # Setup done echo if [ ${#errors[@]} -gt 0 ] then echo 'There were errors:' for e in "${errors[@]}" do echo "Error: $e" done echo exit 1 fi # FIXME On re-runs in already working environments this is mis-leading if $exec_shell_required then echo ' ---------------------------------------------------' echo ' | |' echo ' | To finish the installation run |' echo ' | |' case $os_dist in debian|ubuntu|redhat) echo ' | exec $SHELL |' echo ' | |' echo ' | in this terminal now (mind the "$" in "$SHELL") |' ;; macos) echo ' | exec /bin/bash |' esac echo ' | |' echo ' ---------------------------------------------------' echo fi echo "$setup_basename ($setup_version): Done" echo exit 0