#!/bin/sh #* This program is free software. It comes without any warranty, to #* the extent permitted by applicable law. You can redistribute it #* and/or modify it under the terms of the Do What The Fuck You Want #* To Public License, Version 2, as published by Sam Hocevar. See #* http://sam.zoy.org/wtfpl/COPYING for more details. # #I would appreciate it if any code that is copied and reused was marked as coming from this script. # #********************************* #Author: Cappy of ubuntuforums.org #Version: 1.06 #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 when you only have the library name #********************************* #Notes: #********************************* #Proxy users may need to: export http_proxy="http://username:password@proxy.example.com:8080" #before running # #ToDo: Change to getopts # #Feel free to contribute to the improvement of this script. #********************************* 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 Usage: getlibs -64 amd64librarytoinstall.so 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: If this program needs a 32-bit library use: getlibs -32 i386librarytoinstall.so If this program needs a 64-bit library use: getlibs -64 amd64librarytoinstall.so" clean_up_err } wget_fail() { echo "\ $sitetouse could not be contacted The site may be down or your internet may be disconnected If you are behind a proxy use this before running:" echo 'export http_proxy="http://username:password@proxy.example.com:8080"' clean_up_err } copy_fail() { echo "Copying files failed - run getlibs with \"sudo getlibs\" or as root" 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" PATH="/usr/bin:/bin:/sbin:/usr/sbin:$PATH"; export PATH #Variables tempdir=`mktemp -d /tmp/getlibs.XXXXXXXXXX || echo "Unable to create temp directory in /tmp"; clean_up_err` #Make temp directory #Make sure there at least 1 argument to the program if [ $# -lt 1 ]; then print_usage fi if [ "`echo "$-" | grep "x"`" ]; then debugon="1" #Set to string "1" fi architecture=`uname -m` #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 heron) distroname="heron"; set_site_ubuntu;; gutsy) distroname="gutsy"; set_site_ubuntu;; feisty) distroname="feisty"; 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 if [ "$sitetouse" = "http://packages.debian.org" ]; then shopt -s xpg_echo #Set echo to interpret \n - works already in ubuntu sh fi #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 " Fatal Error: /emul/ia32-linux does not exist Your distro may not have been detected properly 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 " error: \"$1\" is not the name of a shared library The name of a shared object library looks like \"libraryname.so.1\" " print_usage else #if the file name has ".so" in it: if [ -n "$templist" ]; then templist="$templist $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 [ -z "`file "$binaryfile" | grep "ELF"`" ]; 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" 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 #Skip to next if the library is libGL.so.1 if [ "`echo "$libraryneeded" | grep "libGL\.so"`" ]; then echo "libGL is installed from video drivers, please install or reinstall your video drivers" continue fi searchpage1="$sitetouse/cgi-bin/search_contents.pl?word=$libraryneeded&searchmode=searchfiles&case=insensitive&version=$distroname&arch=i386" #wget makes a mess in the debugger, if debug is running turn it off and then back on if [ -n "$debugon" ]; then set +x fi #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 linktopage2=`wget -q -O- "$searchpage1" || wget_fail` #Make sure there is an internet connection linktopage2=`echo "$linktopage2" | grep "\(^usr/lib/[^/]*\|^lib/[^/]*\)[[:space:]]" | grep -o \"[^\<]*\" | grep -v "color:" | sed s/\"//g` if [ -n "$debugon" ]; then set -x fi #Get the first package that matched - "" around variable would list all packages into packagename packagename=`echo $linktopage2 | awk '{print $1}'` #Get rid of the sitename on the front of the links (mainly for debian) packagename=`echo "$packagename" | sed "s-$sitetouse--g"` #Get the filename of the package from the end of the text filename=`echo "$packagename" | grep -o '[^/]*$'` if [ -z "$filename" ]; then echo "No match found for package $libraryneeded" continue fi #different arch library: if [ "$nativedownload" -eq 0 ]; then echo "Matched library $libraryneeded to $packagename" #Find the link to the i386 page that displays the mirrors for the library linktopage3=`wget -q -O- $sitetouse$packagename | grep '\(arch=i386\|arch=all\)' | grep download.pl | grep -o \"[^\<]*\" | sed s/\"//g` #Get the first match linktopage3=`echo $linktopage3 | awk '{print $1}'` if [ -z "$linktopage3" ]; then echo "Error finding a link to the list of download mirrors" continue fi #Find the link to the i386 .deb file that is hosted on a mirror packagedownloadlink=`wget -q -O- $sitetouse$linktopage3 | grep '\(mirrors.kernel.org\|\"http://[^\<]*\.deb\"\)' | grep -o \"http://[^\<]*\.deb\" | sed s/\"//g` #Get the first match in case it can't find mirrors.kernel.org and it matches multiple links packagedownloadlink=`echo $packagedownloadlink | awk '{print $1}'` if [ -z "$packagedownloadlink" ]; then echo "Error finding a download link" continue fi #Store package name downloadlistnames="$downloadlistnames $packagename" #Store link for download downloadlistlinks="$downloadlistlinks $packagedownloadlink" #same arch library: apt-file could also work elif [ "$nativedownload" -eq 1 ]; then echo "Matched library $libraryneeded to $filename" aptgetlist="$aptgetlist $filename" fi done #If installing different arch libraries if [ "`echo "$downloadlistlinks" | grep "[[:alpha:]]"`" ]; then #If there are links to download #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 "." 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/ || copy_fail fi if [ -d $tempdir/extracted/lib/ ]; then #If dir exists (and thus files to move) sudo cp -R $tempdir/extracted/lib/* /lib32/ || copy_fail fi elif [ "$sitetouse" = "http://packages.debian.org" ]; then sudo cp -R $tempdir/extracted/* /emul/ia32-linux/ || copy_fail else echo "Error: Unknown site to use \"$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 $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 dependencylist=`echo "$dependencylist" | grep "[[:alnum:]]"` #Get rid of blank lines #If there are new dependencies - use grep incase there is only white space left and var is not empty if [ -n "$dependencylist" ]; 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