#!/bin/sh # #Getlibs Yin: #********************************* #Author: Cappy of ubuntuforums.org #Version: 1.03.01 #Purpose: Download native and non-native libraries using the web interface provided by packages.debian.org/packages.ubuntu.com #1) Fix the problem of needing 32-bit libraries on a 64-bit system #2) Fix the problem of needing libraries for a binary using only the library name #********************************* #Notes: #********************************* #Proxy users may need to: export http_proxy="http://username:password@proxy.example.com:8080" #before running #How to debug: sh -x /usr/bin/getlibs parameters #Comments are above the code they are commenting #ToDo: Use getopts, be nice to link the libraries correctly to prevent errors #Protect variables with double quotes #********************************* #Getlibs Yang: clean_up() { rm -rf $tempdir #Normal exit without errors } clean_up_err() { rm -rf $tempdir exit 1 #Exit code 1 } print_usage() { echo "Usage: getlibs /path/to/binary" echo "Usage: getlibs -64 amd64librarytoinstall.so" echo "Usage: getlibs -32 i386librarytoinstall.so" clean_up_err } not_an_executable() { echo "Cannot determine the dependencies required by this program, it may be a script:\n" echo "If this program needs a 32-bit library use:" echo "getlibs -32 i386librarytoinstall.so\n" echo "If this program needs a 64-bit library use:" echo "getlibs -64 amd64librarytoinstall.so" clean_up_err } wget_fail() { echo "$sitetouse could not be contacted" echo "The site may be down or your internet may be disconnected" echo "If you are behind a proxy use this before running:" echo 'export http_proxy="http://username:password@proxy.example.com:8080"' clean_up_err } set_site_ubuntu() { sitetouse="http://packages.ubuntu.com" } set_site_debian() { sitetouse="http://packages.debian.org" } #Trap exits trap clean_up_err 1 2 3 13 15 #Called if interrupted by user trap clean_up 0 #Called when program "exits" #Variables tempdir=`mktemp -d /tmp/getlibs.XXXXXXXXXX || echo "Unable to create temp directory"; clean_up_err` #Make temp directory #Make sure there at least 1 argument to the program if [ $# -lt 1 ]; then print_usage fi architecture=`arch` #Select the correct site to download/search on releaseinput=`lsb_release -c | grep -o [[:alnum:]]*$` #grep last word in the distro's codename case $releaseinput in #Ubuntu feisty) distroname="feisty"; set_site_ubuntu;; gutsy) distroname="gutsy"; set_site_ubuntu;; edgy) distroname="edgy"; set_site_ubuntu;; dapper) distroname="dapper"; set_site_ubuntu;; #Debian sid) distroname="unstable"; set_site_debian;; lenny) distroname="testing"; set_site_debian;; etch) distroname="stable"; set_site_debian;; sarge) distroname="oldstable"; set_site_debian;; #Old Ubuntu breezy) distroname="breezy"; set_site_ubuntu;; hoary) distroname="hoary"; set_site_ubuntu;; warty) distroname="warty"; set_site_ubuntu;; #Unknown *) echo "Unknown distro, using Debian Unstable (sid) settings"; distroname="unstable"; set_site_debian;; esac #For someone who won't read install directions that say to install ia32-libs #If 64-bit debian and ia32-libs is not installed if [ "x86_64" = "$architecture" ] && [ "$sitetouse" = "http://packages.debian.org" ] && [ ! -d /emul/ia32-linux ]; then #install ia32-libs sudo apt-get install ia32-libs #Non-debian: if [ ! -d /emul/ia32-linux ]; then echo "\nFatal Error: /emul/ia32-linux does not exist" echo "Your distro may not have been detected properly" echo "Detected as: $architecture debian $distroname" echo `lsb_release -a` clean_up_err fi #If 64-bit ubuntu and ia32-libs is not installed - I selected libGLU since it exists in every versions's ia32-libs elif [ "x86_64" = "$architecture" ] && [ "$sitetouse" = "http://packages.ubuntu.com" ] && [ ! -e "/usr/lib32/libGLU.so.1" ]; then sudo apt-get install ia32-libs ia32-libs-gtk #could check fi #Run only for install by library name if [ $# -gt 1 ]; then if [ "x86_64" = "$architecture" ]; then if [ "$1" = "-32" ]; then #Must download the 32-bit library nativedownload=0 elif [ "$1" = "-64" ]; then #use apt-get nativedownload=1 else print_usage fi elif [ "ppc" = "$architecture" ]; then echo "This script does not work on a ppc" clean_up_err else if [ "$1" = "-32" ]; then #use apt-get nativedownload=1 elif [ "$1" = "-64" ]; then echo "You cannot install 64-bit libraries on a 32-bit OS!" clean_up_err else print_usage fi fi #for each argument add it to the $dependencylist shift while [ "$1" ]; do if [ `echo $1 | grep -ci "\.so"` -eq 0 ]; then #if the file name does not have ".so" in it: echo "\nerror: \"$1\" is not the name of a shared library" echo "The name of a shared object library looks like \"libraryname.so.1\"\n" print_usage else #if the file name has ".so" in it: if [ -n "$templist" ]; then templist=`echo "$templist\n$1"` shift else templist=`echo "$1"` shift fi fi done #Remove the "./" if someone included it thinking it was part of the name of a library #Change + to html code (hex) dependencylist=`echo "$templist" | sed 's/.\///g' | sed s/\+/%2B/g` #end code for manual library install #Run only for binaries else binaryfile=$1 if [ ! -f "$binaryfile" ]; then echo "The file \"$binaryfile\" does not exist" print_usage elif [ ! -r "$binaryfile" ]; then echo "The file \"$binaryfile\" does not have read permissions" clean_up_err elif [ `ldd "$binaryfile" | grep "not a dynamic executable"` ]; then not_an_executable fi #Check to see if the binary is 32-bit or 64-bit isit32bit=`file "$binaryfile" | grep "32-bit"` isit64bit=`file "$binaryfile" | grep "64-bit"` if [ "x86_64" = "$architecture" ]; then if [ "$isit32bit" ]; then #Must download the 32-bit library nativedownload=0 elif [ "$isit64bit" ]; then #use apt-get nativedownload=1 else not_an_executable fi else if [ "$isit32bit" ]; then #use apt-get nativedownload=1 elif [ "$isit64bit" ]; then echo "This isn't a 32-bit application:" echo `file $binaryfile` clean_up_err else not_an_executable fi fi cd `dirname "$binaryfile" || echo "cd $binaryfile failed"; clean_up_err` #Change to the program's directory binaryfile=`basename "$binaryfile"` #print program dependencies | find the ones missing | get only the library names | replace "+" with %2B dependencylist=`ldd "$binaryfile" | grep "not found" | awk '{print $1}' | sed s/\+/%2B/g` #Local needed libraries - message instead of automatic because sometimes the dependency is renamed without a number neededlocallibraries=`echo "$dependencylist" | grep "\./" | sed 's/\.\///g'` #get rid of the "./" on the front of the library name if [ "$neededlocallibraries" ]; then echo "You need to be copy the following libraries to the same directory as the binary:" echo "$neededlocallibraries" #get rid of the "./" on the front of the library name fi #get rid of libraries starting with "./" dependencylist=`echo "$dependencylist" | grep -v \./` #get the first missing library out of the list | replace "+" with %2B if [ -z "`echo "$dependencylist" | grep "[[:alpha:]]"`" ]; then echo "This application isn't missing any dependencies" exit fi fi #end code for binaries while [ -n "`echo "$dependencylist" | grep "[[:alpha:]]"`" ]; #Loop for incase there are new dependencies created by the new libraries do #Get rid of duplicate lines libraries=`echo "$dependencylist" | sort -u` #For each missing library libraryneeded="" for libraryneeded in $libraries; #Could use Parallel execution here do searchpage1="$sitetouse/cgi-bin/search_contents.pl?word=$libraryneeded&searchmode=searchfiles&case=insensitive&version=$distroname&arch=i386" #Look up library name | look for packages that are in /usr/lib or /lib and no subdirectories #| pull text out between double quotes (other than color:red) | get rid of double quotes #wget makes a mess in the debugger, if debug is running turn it off and then back on if [ "`echo "$-" | grep "x"`" ]; then set +x linktopage2=`wget -q -O- "$searchpage1" || wget_fail` linktopage2=`echo "$linktopage2" | grep "\(^usr/lib/[^/]*\|^lib/[^/]*\)[[:space:]]" | grep -o \"[^\<]*\" | grep -v "color:" | sed s/\"//g` set -x else linktopage2=`wget -q -O- "$searchpage1" || wget_fail` linktopage2=`echo "$linktopage2" | grep "\(^usr/lib/[^/]*\|^lib/[^/]*\)[[:space:]]" | grep -o \"[^\<]*\" | grep -v "color:" | sed s/\"//g` fi #Get the first package that matched - "" around variable would list all packages into packagename packagename=`echo $linktopage2 | awk '{print $1}'` if [ "$sitetouse" = "http://packages.debian.org" ]; then #The debian page includes "http://packages.debian.org" on the front of their links packagename=`echo "$packagename" | sed 's+http://packages.debian.org++g'` fi #Get the filename of the package from the end of the text filename=`echo "$packagename" | grep -o '[^/]*$'` #different arch library: if [ "$nativedownload" -eq 0 ]; then if [ -z "$packagename" ]; then echo "No match found for 32-bit package $libraryneeded" else echo "Matched library $libraryneeded to $packagename" #Against Unix tradition of output #Find the link to the i386 download page for the library linktopage3=`wget -q -O- $sitetouse$packagename | grep 'arch=i386' | grep download.pl | grep -o \".*\" | sed s/\"//g` #Find the link for the i386 .deb file packagedownloadlink=`wget -q -O- $sitetouse$linktopage3 | grep mirrors.kernel.org | grep -o http.*\.deb\" | sed s/\"//g` #Store package name downloadlistnames=`echo "$downloadlistnames\n$packagename"` #Store link for download downloadlistlinks=`echo "$downloadlistlinks\n$packagedownloadlink"` fi #same arch library: apt-file could also work elif [ "$nativedownload" -eq 1 ]; then if [ -z "$linktopage2" ]; then #if var is null echo "No match found for $libraryneeded" else if [ "$filename" = "" ]; then echo "No package match found for $libraryneeded" else echo "Matched library $libraryneeded to $filename" #Against Unix tradition of output aptgetlist=`echo "$aptgetlist\n$filename"` fi fi fi done #If installing different arch libraries if [ "`echo "$downloadlistnames" | grep "[[:alpha:]]"`" ]; then #If there are names in the list #Sort list of names and download links downloadlistnames=`echo "$downloadlistnames" | sort -u` downloadlistlinks=`echo "$downloadlistlinks" | sort -u` #-n since there is only a blank line at the beginning of $downloadlistnames/$downloadlistlinks echo -n "The following i386 libraries will be installed:" echo "$downloadlistnames" echo -n "Continue? (y/n) " read prompt case $prompt in n|N) exit;; [nN][oO]) exit;; y|Y) ;; [yY][eE][sS]) ;; *) echo "Not understood. Aborting."; clean_up_err; esac packagedownloadlink="" echo -n "Downloading" for packagedownloadlink in $downloadlistlinks; do echo -n "." sudo wget -q "--directory-prefix=$tempdir" $packagedownloadlink #Get the filename of the deb filename=`basename $packagedownloadlink` #Extract the debian dpkg -x "$tempdir/$filename" "$tempdir/extracted" done echo "Installing libraries ..." if [ "$sitetouse" = "http://packages.ubuntu.com" ]; then if [ -d $tempdir/extracted/usr/lib/ ]; then #If dir exists (and thus files to move) sudo cp -R $tempdir/extracted/usr/lib/* /usr/lib32/ fi if [ -d $tempdir/extracted/lib/ ]; then #If dir exists (and thus files to move) sudo cp -R $tempdir/extracted/lib/* /lib32/ fi elif [ "$sitetouse" = "http://packages.debian.org" ]; then sudo cp -R $tempdir/extracted/* /emul/ia32-linux/ else echo 'Error: Unknown $sitetouse while installing 32-bit libraries' clean_up_err fi sudo ldconfig #Update ldconfig if [ -n "$binaryfile" ]; then #if there was a binaryfile passed as input at beginning of program #Store dependencies runningdependencylist="$runningdependencylist\n$dependencylist" dependencylist=`ldd "$binaryfile" | grep "not found" | awk '{print $1}' | grep -v "\./" | sed s/\+/%2B/g` #Get rid of dependencies that have already been tried by removing them from the new $dependencylist for eachdependency in $runningdependencylist; do dependencylist=`echo "$dependencylist" | sed "s/$eachdependency//g"` done #If there are new dependencies - use grep incase there is only white space left and var is not empty if [ "`echo "$dependencylist" | grep "[[:alpha:]]"`" ]; then rm -rf $tempdir/* #Remove everything except the $tempdir folder echo "New depedencies have been detected:" echo "$dependencylist" #Clear out old data downloadlistnames="" downloadlistlinks="" else exit #No new dependencies fi else exit #Exit if installing from -32 on a 64-bit system fi #If installing same arch libraries elif [ -n "$aptgetlist" ]; then aptgetlist=`echo "$aptgetlist" | sort -u` sudo apt-get install $aptgetlist exit else echo "No libraries to download." exit fi done