#!/bin/bash # Stream producers # # These produce a stream of escaped new-line separated items # # Stream the given arguments # VGL_sourceS() { ( printf '%q\n' "$@" ) || (( $? == 141 )) } # Stream the results of the given command # VGL_systemS() { declare -a command=("$@") ( eval $(printf '%q ' "${command[@]}") ) || (( $? == 141 )) } # Stream the results of find (correctly escapes all filenames) # VGL_findS() { declare -a options=("$@") file VGL_systemS find "${options[@]}" -print0 | while read -d '' -r file; do VGL_sourceS "$file" done } # Stream the closure of the list libraries from an elf file # VGL_elfLibsS() { declare file=$1 line VGL_systemS ldd "$file" | while read line; do line=${line#$'\t'} case "$line" in *' => not found') line=${line% => not found} ;; *' => '*' ('*')') line=${line#* => } line=${line% (*)} ;; *' ('*')') line=${line% (*)} ;; esac VGL_sourceS "$line" done } # Stream transformers # # Take in a set of options and transform a stream of new-line separated items # # Group all items onto a single line separated by given deliminator (or space) # VGL_joinS() { declare deliminator=${1- } next if read next; then printf '%q' "$next" while read next; do printf '%s%q' "$deliminator" "$next" done printf '\n' fi } # Remove all items for which the given command returns false # VGL_filterS() { declare command=("$@") while read next; do if eval $(printf '%q ' "${command[@]}" "$next"); then VGL_sourceS "$next" fi done } # Stream consumers # # These consume a stream of escaped new-line separated items # VGL_anyS() { declare command=("$@") while read next; do if eval $(printf '%q ' "${command[@]}" "$next"); then return 0 fi done return 1 } # Tests for the filter transformer # # Check for an elf file (binary or library) # VGL_isElfBin() { declare file=$1 case "$(file -b -N --mime-type "$file")" in application/x-executable | application/x-pie-executable) return 0 ;; *) return 1 ;; esac } # Check for libGL # VGL_isLibGL() { declare file=$1 case "$file" in libGL.so* | */libGL.so*) return 0 ;; *) return 1 ;; esac } # Setup hook # # Find all executables that depend on libGL and add a libvglfaker.so dependency # VGL_autoAddVGL() { echo "Inserting VirtualGL into OpenGL executables in $prefix..." >&2 for output in $outputs; do VGL_findS "${!output}" -type f | VGL_filterS VGL_isElfBin | { declare file while read file; do VGL_elfLibsS "$file" | if VGL_anyS VGL_isLibGL; then VGL_sourceS "$file" fi done } | { declare file while read file; do printf 'patchelf --add-needed @virtualglLib@/lib/libvglfaker.so %q\n' "$file" >&2 patchelf --add-needed @virtualglLib@/lib/libvglfaker.so "$file" done } done } postFixupHooks+=(VGL_autoAddVGL)