Codebase list debian-goodies / a2bc633 debmany / debmany
a2bc633

Tree @a2bc633 (Download .tar.gz)

debmany @a2bc633raw · history · blame

#!/bin/bash
# script:      debmany
# author:      Michael Arlt
# description: select the manpages of any [not] installed debian package
# comment:     debmany is based on the work of debman and debget
# uses:        whiptail (preferred) or dialog
# This is free software.  You may redistribute copies of it under the terms of
# the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.
# There is NO WARRANTY, to the extent permitted by law.

LC_ALL=C

# choose the manpageviewer
mancmdline="man %s" # default manpageviewer

curdir=`pwd`

error()
{
  # show errorcode and quit
  echo "ERROR: $*" >&2
  exit 1
}

usage()
{
  echo "debmany 1.2 Sat Aug 25 22:38:17 CEST 2007
Description: Display a manpage from a Debian package.
             The list of manpages is displayed in a dialog.
             Supported locations for debian packages are: Local .deb-file,
             a package in the repository or a installed package.
Syntax1 : debmany [-?|-h|--help]
Syntax2 : debmany [-m viewer|-k|-g|-x] [-L limit] [-l lang1[,...]] package[.deb]
Examples: debmany foo.deb  show manpages from a local package file foo.deb
          debmany foo      show manpages from a package, if the package is
                           not installed it is retrieved from the
                           configured repositories.
          debmany -k foo   show manpages using your preferred man-viewer (KDE)
          debmany -g foo   show manpages using your preferred man-viewer (GNOME)
          debmany -x foo   show manpages using your preferred man-viewer
                           using xdg-open from xdg-utils package (Xfce users)
          debmany -m 'konqueror man:%s' -l de,fr -L 5M foo
                           show english, german and french manpages using
                           konqueror as man-viewer and ask if download size
                           exceeds 5M
          alias debmany='debmany -l de -L 5M -k'; debmany -m man -l "*" foo
                           set an alias with your preferred options and
                           overwrite them if needed"
  if [ $# -eq 0 ]
  then
    exit 0
  else
    error "$*"
  fi
}

while [ $# -gt 0 ]
do
  case $1 in
  "-?"|-h|--help) usage ;;
  -m) # override default manpageviewer or environment variable DEBMANY_MAN_VIEWER
      shift
      mancmd=($1)			# get first word from manpageviewer
      if which $mancmd >/dev/null 2>&1	# is the manpageviewer executeable?
      then
        echo $1 | grep -q "%s" && mancmdline="$1" || mancmdline="$1 %s"
      else
        usage "Manpageviewer '$mancmd' is not available or executable"
      fi
  ;;
  -k) mancmdline='kfmclient exec man:%s';;	# set kde viewer
  -g) mancmdline='gnome-open man:%s';;		# set gnome viewer
  -x) mancmdline='xdg-open man:%s';;		# set independant viewer
  -l) shift; lang=$1;;				# remember language
  -L) shift; asksize=$1;;			# remember asksize
  -*) usage "Unknown option '$1'.";;
  *)  package="$1";;
  esac
  shift
done

test -z "$package" && usage "You must specify one package or a Debian package file."

# determine the size of your terminal
declare -i size=(`stty size`)
declare -i x=${size[1]}
declare -i y=${size[0]}

# if it is impossible to determine the size
if [ $x -eq 0 ]
then
  x=80
  y=25
  echo "Unable to determine the size of your terminal - using Console default: $x*$y" >&2
  sleep 3
fi

# test upon minimum resolution
if [ $x -lt 40 -o $y -lt 9 ]
then
  error "Resolution too small ($x*$y). I need a minimum of 40*9 - recommended is more..."
fi

# set the size of the dialog window and menu
x=x-1			# width of the dialog
y=y-1			# height of the dialog
declare -i h=y-7	# height of the menu

if [ "${package##*.}" = "deb" ] 
then
  # mode1: you want to see manpages from a .deb-file
  if [ -r "$package" ]
  then
    file=`readlink -f "$package"`
    status=file
  else
    error "The file $package cannot be read."
  fi
else
  # mode 2: test if you have the package already installed
  if dpkg -l "$package" 2>/dev/null | grep -q ^i
  then
    status=installed
    set -f
    # modify lang for grep regular expressions: fr -> fr\.* (-> fr+fr.ISO8859-1+"fr."...)
    langgrep=`echo $lang|sed -e s/*/.*/g -e 's/\([a-zA-Z_][a-zA-Z_]*\)/\1,\1\\\\\\.*/'`
    # create the list of all mandirs (with -e for grep) (X11R6 is only for sarge - didn't find it in etch anymore)
    mandirs="`eval echo \\"-e \\"/usr/\{share,X11R6\}/man/man.*/ \\"-e \\"/usr/\{share,X11R6\}/man/\{$langgrep,XYZZXY\}/`"
    for man in `dpkg -L "$package" 2>/dev/null|grep $mandirs|sort`
    do
      # mode 2: add the manpages to the list
      test -f $man && manpages="$manpages $man ${man##*/}"
    done
    set +f
  fi
fi

# choose whiptail or dialog
whiptail=/usr/bin/whiptail
dialog=/usr/bin/dialog
test -x $whiptail && cmd=$whiptail || cmd=$dialog

if [ "$status" = "installed" ]
then
  # mode 2
  cd /
else
  # mode 1 and 3
  trap 'test -n "$temp" && rm -rf $temp; exit' 0 2 15 # cleanup

  tmp=/dev/shm			# set default tempdir
  test -d $tmp || tmp=/tmp	# if not available use /tmp

  # make a temporary folder for the manpages - $TMPDIR overrides the path of -p
  temp=`mktemp -d -p $tmp debmany.XXXXXXXXXX` || error "Unable to create a temporary folder."

  if [ -z "$file" ]
  then
    # mode 3: find the package.deb
    aptdata=`apt-get -q2 --print-uris --reinstall install "$package" 2>/dev/null | tail -1`
    if [ -z "$aptdata" ]
    then
      error "There is no package called '$package'."
      exit 1
    fi

    url=`echo "$aptdata" | sed -e "s/^'\([^']*\)'.*$/\1/"`
    test -z "$url" && error "Could not obtain an URL for '$pkgspec'."

    if [ "${url%%:*}" = "file" ]
    then
      # mode 3: access the local file
      file="${url#*:}"
      if [ ! -r "$file" ]
      then
        error "Could not access '$file' from the repository."
      fi
      status=repos-file
    else
      # mode 3: download the local file
      file="$temp/tmp.deb"
      # if i should ask at a specific size
      if [ "$asksize" != "" ]
      then
        # determine the size of the file to download (*10 for 10,5M)
        declare -i size=`apt-cache show "$package"|grep ^"Size: "|cut -f2 -d" "|head -1`*10
        # determine the value of ask_size
        templimit=`echo ${asksize//[^0-9]/}`
	test "$templimit" = "" && error "Parameter -L needs an argument - e.g. '10M'."
        declare -i limit=`echo ${asksize//[^0-9]/}`*10
        # determine the unit of ask_size
        unit=`echo ${asksize//[0-9]/}`
        # calculate the limit according to unit from DEBMANY_ASK_SIZE
        case $unit in
          B|"") ;;
          K) limit=limit*1024;;
          M) limit=limit*1024*1024;;
          G) limit=limit*1024*1024*1024;;
          T) limit=limit*1024*1024*1024*1024;;
          *) error "Invalid unit '$unit' in variable DEBMANY_ASK_SIZE."
        esac
        # calculate the human readable size and ask for download if size exceeds limit
        if [ $size -ge $limit ]
        then
          unit=B
          # reduce the size and correct the unit until it is human readable
          while [ $size -gt 1024 ]
          do
            size=size/1024
            case $unit in
              G) unit=T;;
              M) unit=G;;
              K) unit=M;;
              B) unit=K;;
            esac
          done
          # set the comma (so if the file has a size of 50M we change 500 to 50,0M
          commasize=`echo $size|sed "s/\([0-9]*\)\([0-9]\)/\1,\2/"`$unit
          # ask if the download may start - otherwise debmany exits
          if ! $cmd --yesno "Would you like to download the package with a size of $commasize?" 9 40
          then
            echo "Download undesired - $commasize is too big."
            exit
          fi
        fi
      fi
      curl "$url" >"$file" || error "Could not download '$file' from the repository."
      status=repos-curl
    fi
  fi
  cd $temp
  # extract the manpages
  set -f
  # modify lang for pathname expansion: fr -> fr.* (-> fr+fr.ISO8859-1+"fr."...)
  lang=`echo $lang|sed -e 's/\([a-zA-Z_][a-zA-Z_]*\)/\1,\1*/'`
  # create the list of all mandirs (X11R6 is only for sarge - didn't find it in etch anymore)
  mandirs="`eval echo \{./,\}usr/\{share,X11R6\}/man/man*/ \{./,\}usr/\{share,X11R6\}/man/\{$lang,XYZZXY\}/`"
  dpkg --fsys-tarfile "$file" | tar --wildcards -xf - $mandirs 2>/dev/null
  set +f
  manpages=`find usr -type f|sort|sed -e 's§\([^/]*\)$§\1 \1§'`
fi

while true
do
  # test if manpages where found
  test -z "$manpages" && error "No manpage exists for package '$package'."

  # select your manpages using dialog
  exec 3>&1
  return=`$cmd --title "Select a manpage ($status:$package)" --menu '' $y $x $h $manpages 2>&1 1>&3`
  exec 3>&-
  if [ -n "$return" ]
  then
    # show the manpage
    `printf "$mancmdline" "$PWD/$return"`
  else
    cd $curdir
    exit
  fi
done

# This should not be reached
cd $curdir
exit 0