#!/bin/ash
#
#  pkg - a command line package manager for Puppy Linux
#
#  By Scott Jarvis (sc0ttman)
#
#  Copyright (c) 2013 Puppy Linux Community
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 1 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <http://www.gnu.org/licenses/>.

{
#==================  setup script vars  =====================#

APPNAME="Pkg"
APPVER="1.9.21alpha"
APPTITLE="$APPNAME $APPVER"

# get current locale settings
USER_LANG=$LANG
USER_LC_ALL=$LC_ALL

export SELF=$(basename $0)        # this script
export QTAG=''                    # gets set to (y/n) if ASK=-true
export LANG=C                     # speed up
export LC_ALL=C                   # speed up
export EDITOR=${EDITOR:-nano}     # just in case
export PAGER=${PAGER:-less}       # just in case
export CURDIR="${PWD}"            # get current dir, before cd to WORKDIR
export TMPDIR=/tmp/pkg/${whoami}  # set the tmp dir
export CP_SUFFIX=PLUSDEPS         # appended to combined pkgs (pkg+deps) 

# set colours true by default
green="\e[32m"; red="\e[91m"; magenta="\e[95m"; lightblue="\e[36m"; yellow="\e[93m"; bold="\e[1m"; endcolour="\e[0m"

# ENVIRONMENT VARS, which may overridden later
[ -z "$PKGRC" ] && export PKGRC=${HOME}/.pkg/pkgrc      # config file for this script
[ -z "$ASK"   ] && export ASK=false                     # if true, ask user before doing stuff. Overridden by --ask
[ -z "$QUIET" ] && export QUIET=false                   # if true, hide output that doesnt log well in Xdialog, Gtkdialog, etc
[ -z "$FORCE" ] && export FORCE=false                   # if true, force (re)install/remove pkgs. Overridden by --force
[ -z "$HIDE_INSTALLED" ] && export HIDE_INSTALLED=false # if true, hide installed pkgs from pkg searches (-n, -na, -ss, -ssa)
[ -z "$HIDE_BUILTINS"  ] && export HIDE_BUILTINS=true   # if true, remove builtins pkgs from dep lists, dont download/install them
[ -z "$HIDE_USER_PKGS" ] && export HIDE_USER_PKGS=true  # if true, hide user installed pkgs from dep lists, dont download/install them
[ -z "$NO_ALIASES"     ] && export NO_ALIASES=false     # if true, skip searching pkg alias names for pkg alternatives
[ -z "$NO_INSTALL"     ] && export NO_INSTALL=false     # if true, skip installing of pkgs
[ -z "$PKG_NO_COLOURS" ] && export PKG_NO_COLOURS=false # if true, disable coloured output or not

# but disable colours if called as gpkg, or the ENV variable PKG_NO_COLOURS is true
if [ "`basename $0`" != "pkg" -o "$PKG_NO_COLOURS" = true ];then
  green='' red='' magenta='' lightblue='' yellow='' bold='' endcolour=''
fi

# report errors better than just echo
error(){
  echo -e 1>&2 "${red}Error:${endcolour} $1"
}

# for correct error output, trap commands early
cleanup(){
  rm -f ${TMPDIR}missing_dep* ${TMPDIR}installed_pkg* ${TMPDIR}all_dep* ${TMPDIR}DEP_DONE /tmp/pkg/list_deps_busy ${TMPDIR}pkg_file_list ${TMPDIR}/dependents_list ${TMPDIR}DEP_DONE ${TMPDIR}ldd_file_list &>/dev/null
  
  # prevent double msg output if error=130 (user Ctrl-C)
  [ -f /tmp/pkg/error130 -a "$2" = '130' ] && exit "$2"
  # make the tmp dir we'll use
  mkdir -p /tmp/pkg &>/dev/null
  # only add line numbers if it was given
  [ "$1" != 'none' ] && lineno="line $1, " || lineno=''
  # get the right error msg
  case "$2" in
  130) echo; msg="User cancelled operation!"; touch /tmp/pkg/error130;;
  8)   msg="Package URL invalid.";;
  7)   msg="Package extraction failed.";;
  6)   msg="Missing package file.";;
  5)   msg="Missing directory.";;
  4)   msg="Copy failed.";;
  3)   msg="Setup failed.";;
  2)   msg="Code error!";;
  1)   exit 1 ;; # user gave wrong options or pkg name, not serious
  *)   msg="Error code = $2" ;;
  esac
  # print msg
    [ "$2" != "0" ]  && echo -e 1>&2 "${red}Error${endcolour} ${2}: ${lineno}$msg"
    # clean up
    make clean &>/dev/null
    exit $2
}
trap 'cleanup ${LINENO:-none} $?' EXIT INT TERM

#run as root only
whoami=$(whoami)
[ "$whoami" != "root" ] && echo "You must be root to run Pkg." && exit 1

#080413 make sure all config files are present, copy from /etc if need be
if [ ! -f ${PKGRC} ];then
  echo "Restoring default settings from /etc/pkg"
  [ ! -d /etc/pkg/ ] && error "Default config files  in /etc/pkg/ not found." && exit 3
  mkdir -p "$HOME/.pkg"
  [ ! -d "$HOME/.pkg" ] && error "Default user config dir '$HOME/.pkg/' could not be created." && exit 3
  cp --force -a /etc/pkg/* "$HOME/.pkg/" || exit 3
fi

# get puppy distro env vars
[ -f /etc/rc.d/PUPSTATE ]                 && . /etc/rc.d/PUPSTATE                #this has PUPMODE and SAVE_LAYER.
[ -f /etc/DISTRO_SPECS ]                  && . /etc/DISTRO_SPECS                 #has DISTRO_BINARY_COMPAT, DISTRO_COMPAT_VERSION
[ -f /etc/rc.d/BOOTCONFIG ]               && . /etc/rc.d/BOOTCONFIG              #has EXTRASFSLIST PREVUNIONRECORD, LASTUNIONRECORD (sfs stuff)
[ -f /etc/xdg/menus/hierarchy ]           && . /etc/xdg/menus/hierarchy          #w478 has PUPHIERARCHY variable.
[ -f $HOME/.packages/DISTRO_PKGS_SPECS ]  && . $HOME/.packages/DISTRO_PKGS_SPECS #has lot sof essential info

# set correct arch for repo URLs
case "$DISTRO_TARGETARCH" in
  x86)    export DBIN_ARCH=i486                       ;;
  x86_64) export DBIN_ARCH=x86_64 ; export DSUFFIX=64 ;;
  *)      export DBIN_ARCH=i486                       ;;
esac

# needed for some debian based repos
case $DISTRO_COMPAT_VERSION in
  wheezy) DDB_COMP=bz2 ;; # older versions
  *)      DDB_COMP=xz  ;;
esac 

# now create 'layers-installed': will contain builtins (and devx packages, if devx is loaded)
#130511 need to include devx-only-installed-packages, if loaded...
if which gcc &>/dev/null;then
  cp -f $HOME/.packages/woof-installed-packages /tmp/ppm-layers-installed-packages
  cat $HOME/.packages/devx-only-installed-packages >> /tmp/ppm-layers-installed-packages
  sort -u /tmp/ppm-layers-installed-packages > $HOME/.packages/layers-installed-packages
else
  cp -f $HOME/.packages/woof-installed-packages $HOME/.packages/layers-installed-packages
fi

# set $DIRECTSAVEPATH (where we want to install pkgs)
if [ $PUPMODE -eq 3 -o $PUPMODE -eq 7 -o $PUPMODE -eq 13 ];then
  DIRECTSAVEPATH="/initrd${SAVE_LAYER}" #SAVE_LAYER is in /etc/rc.d/PUPSTATE.
elif [ "$PUPMODE" = "2" ]; then
  DIRECTSAVEPATH=""
fi

# get repo details, workdir, search settings and so on.. you could 
# also add any ENVIRONMENT VARS above to PKGRC, to override the defaults
. ${PKGRC} 

# set and create workdir if no valid dir set
[ ! -d "$WORKDIR" ] && mkdir -p "$WORKDIR"
if [ ! -d "$WORKDIR" ];then
  error "Can't create $WORKDIR. Please create it."
  exit 3
fi
export WORKDIR=~/pkg 

# add to tab completion settings to bashrc and print hint
if [ "`grep -m1 '/etc/bash_completion.d/pkg' ~/.bashrc 2>/dev/null`" = "" ];then
  # add to bash rc
  echo "
# enable $APPNAME $APPVER TAB completion
. /etc/bash_completion.d/pkg 2>/dev/null" >> ~/.bashrc
  # print msg
  echo -e "Run ${bold}source /etc/bash_completion.d/pkg${endcolour} to enable "
  echo "TAB auto-completion of package and repo names."
fi

# make tmp dir writable by everyone if needed
if [ ! -d "$TMPDIR" ];then
  mkdir -p "$TMPDIR" 2>/dev/null 
  chmod -R 1777 /tmp/pkg/ 2>/dev/null 
fi

# if no tmp dir created or accessible, exit
[ ! -d "$TMPDIR" ] && error "Cannot create temp dir ${lightblue}$TMPDIR${endcolour}" && exit 3

# support aliases, create ALIASES tmp file
export PKG_NAME_ALIASES='mozilla-firefox,firefox gtk+,gtk2 gtk2,gtk+2 dirac,schroedinger hunspell,myspell mp,mped mplayer,mplayer_*,mplayer-*,mplayer2,smplayer,gmplayer mrxvt,rxvt-unicode,xterm,urxvt,urxvt-unicode cxxlibs,glibc*,libc-* glibc-solibs,glibcsolibs alsalib,alsa-lib,alsa-lib2* alsautils,alsa-utils,alsa_utils,alsa-utils2* libungif,libgif,giflib zip,infozip dbus,libdbus*,libdbus-glib* hal,libhal* mesa,mesa_*,libgl1-mesa*,mesa-common* libxcb,libxcb_base sane,sane-backends samba,samba-tng,samba_*,mountcifs SDL_*,libsdl_* SDL,libsdl skype,skype_static util_linux_ng,util-linux-ng,util-linux,util_linux,utillinuxng vlc,vlc-nogui,vlc_nogui,VLC_Plus_Extras xf86-video-ati,xf86-video-ati-*,ati_fglrx xfdiff,xfdiff-cut xorg_base,xorg_base_t2,x11-common,x-dev,xorg,xorg73_base_t2 acl,libacl* xdg_puppy,xdg-utils perl_tiny,perl-base,perl-modules,perlapi* xorg-util-macros,util-macros portaudio,libportaudio jack-audio-connection-kit,libjack libjasper,jasper imlib2,libimlib2 imlib,libimlib'
[ ! -f "$TMPDIR/pkg_aliases" ] && echo "$PKG_NAME_ALIASES" | tr ' ' '\n' > $TMPDIR/pkg_aliases

# remove error code flag if we got here
rm -f /tmp/pkg/error130 &>/dev/null

# if not first run, and no options given, print the help
[ ! -f ~/.pkg/firstrun -a "$1" = "" ] && $SELF -H && exit 1 #200913 more help by default
}
#==================  setup script vars  =====================#


{
#====================  main functions  ======================#

set -a 

# utility funcs

print_usage(){                    # print usage text. Requires $1, a valid Pkg cmd FUNCLIST
  
  local examples_file=/usr/lib/pkg/docs/examples.txt
  
  [ -f $examples_file ] && source $examples_file
  
  # get and print the usage info from its usage file
  if [ -f /usr/lib/pkg/docs/usage/$1 -a "$1" ];then
    source /usr/lib/pkg/docs/usage/$1
    echo -e "\n$USAGE"
    # show examples, taken from $EXAMPLES, if they exist
    if [ "`echo "$EXAMPLES" | grep "$SELF" | grep "\-$1"`" != '' ];then
      echo -e "\n${bold}Usage Examples${endcolour}:\n"
      echo -e "$EXAMPLES" | grep "$SELF" | grep "\-$1"
    fi
  else
    echo -e "Usage: ${bold}$SELF --usage CMD${endcolour}"
    echo
    echo "Commands:"
    echo -e "add-source     get-only         repo-convert
all            help             repo-dep-scope
all-pkgs       help-all         repo-file-list
ask            install          repo-info
autoclean      install-all      repo-list
bleeding-edge  list-deps        repo-pkg-scope
clean          list-downloaded  repo-update
contents       list-installed   search
deb2pet        names            search-all
delete         names-all        sfs2pet
delete-all     names-exact      sfs-combine
deps           names-exact-all  show-config
deps-all       pet2sfs          tgz2pet
deps-check     pet2tgz          txz2pet
deps-download  pet2txz          uninstall
dir2pet        build            uninstall-all
dir2sfs        build-list       unpack
dir2tgz        pkg-combine      update-sources
download       installed        version
examples       repack           which
extract        status           which-repo
force          update           recursive-dep-check
func-list      workdir          what-needs
Usage: ${bold}$SELF --usage CMD${endcolour}"
    #cd /usr/lib/pkg/docs/usage/; echo `ls` | fold -w 70 -s
  fi
  exit 1
}


func_list(){                      # list all functions available in this script FUNCLIST
  [ -f $TMPDIR/func_list ] && cat $TMPDIR/func_list | sort && exit 0
  grep "(){" $0 | grep '#' | grep FUNCLIST | sed -e 's|^| |g' -e 's|{||g' -e 's|  | |g' -e 's|# ||g' -e 's| FUNCLIST||g' | grep -v 'FUNCLIST $0' | sort > $TMPDIR/func_list
  cat $TMPDIR/func_list | sort
  exit 0
}


get_pkg_ext(){                    # return file extension of given pkg FUNCLIST
  
  # get valid usage or exit
  [ ! "$1" ] && echo 'Usage: get_pkg_ext PKGNAME' && exit 1
  
  local pkg_installed
  local pkg_filename
  local pkg_ext
  
  # check given file type, see if it matches our supported pkg types
  case "$1" in 
    *.bz2)        echo bz2        ;;
    *.pet)        echo pet        ;;
    *.deb)        echo deb        ;;
    *.pkg.tar.gz) echo pkg.tar.gz ;;
    *.pkg.tar.xz) echo pkg.tar.xz ;;
    *.pkg.tgz)    echo pkg.tgz    ;;
    *.pkg.txz)    echo pkg.txz    ;;
    *.tar.bz2)    echo tar.bz2    ;;
    *.tar.lzma)   echo tar.lzma   ;;
    *.tar.gz)     echo tar.gz     ;;
    *.tar.xz)     echo tar.xz     ;;
    *.tbz)        echo tbz        ;;
    *.tgz)        echo tgz        ;;
    *.tlz)        echo tlz        ;;
    *.txz)        echo txz        ;;
    *.gz)         echo gz         ;;
    *.xz)         echo xz         ;;
    *.rpm)        echo rpm        ;;
    *.sfs)        echo sfs        ;;
    #*.tcz)        echo tcz       ;;
    #*.tpkg)       echo tpkg      ;;
    #*.apk)        echo apk       ;;
    *)
      # if it's an installed pkg, get the extension from $HOME/.packages/*
      pkg_installed=`list_installed_pkgs "$1" | grep -m1 "^$1"`
      
      # if $pkg_check not empty, then $1 is an installed pkg
      if [ "$pkg_installed" != '' ];then
        pkg_filename=`cut -f8 -d'|' $HOME/.packages/user-installed-packages |grep -m1 ^$1`
        [ "$pkg_filename" = '' ] && pkg_filename=`cut -f8 -d'|' $HOME/.packages/*-installed-packages |grep -m1 ^$1`
        pkg_ext=`get_pkg_ext "$pkg_filename"`
        [ "$pkg_ext" != '' ] && echo $pkg_ext
      fi
    
      ;;
  esac
}


get_pkg_name_only_from_ext(){     # for ubuntu/debian/etc pkg naming

  # get valid usage or exit
  [ ! "$1" ] && echo 'Usage: get_pkg_name_only_from_ext <PKG_FILENAME>' && exit 1
  
  # get the extension of the given package name, if any
  local pkg_ext=`get_pkg_ext "$1"`
  # get the name without path and extension
  local pkg_name=`basename "$1" .$pkg_ext`
  local PKGNAME=''
  local PKGNAME_ONLY=''
  local DB_pkgrelease=''
  local prPATTERN=''
  local DB_version=''
  local xDB_version=''
  local xPATTERN=''

  #split PKGMAIN, ex: FULLPKGNAME=xvidtune-1.0.1-i486-1.tgz has PKGNAME=xvidtune-1.0.1
  case $pkg_ext in
    deb)
     #deb ex: xsltproc_1.1.24-1ubuntu2_i386.deb  xserver-common_1.5.2-2ubuntu3_all.deb
     PKGNAME_ONLY="`echo -n "$pkg_name" | cut -f 1 -d '_'`"
     DB_pkgrelease="`echo -n "$pkg_name" | rev | cut -f 2 -d '_' | cut -f 1 -d '-' | rev`"
     prPATTERN="s%\\-${DB_pkgrelease}.*%%"
     PKGNAME="`echo -n "$pkg_name" | sed -e "$prPATTERN"`"
     DB_version="`echo "$PKGNAME" | cut -f 2 -d '_'`"
    ;;
    pet)
     PKGNAME="$pkg_name"
     DB_version="`echo -n "$PKGNAME" | grep -o '\\-[0-9].*' | sed -e 's%^\-%%'`"
     xDB_version="`echo -n "$DB_version" | sed -e 's%\\-%\\\\-%g' -e 's%\\.%\\\\.%g'`"
     xPATTERN="s%${xDB_version}%%"
     PKGNAME_ONLY="`echo -n "$PKGNAME" | sed -e "$xPATTERN" -e 's%\\-$%%'`"
     DB_pkgrelease=""
    ;;
    tgz|txz)
     #slack ex: xvidtune-1.0.1-i486-1.tgz  printproto-1.0.4-noarch-1.tgz
     PKGNAME="`echo -n "$pkg_name" | sed -e 's%\\-i[3456]86.*%%' -e 's%\\-noarch.*%%'`"
     DB_version="`echo -n "$PKGNAME" | grep -o '\\-[0-9].*' | sed -e 's%^\\-%%'`"
     xDB_version="`echo -n "$DB_version" | sed -e 's%\\-%\\\\-%g' -e 's%\\.%\\\\.%g'`"
     xPATTERN="s%${xDB_version}%%"
     PKGNAME_ONLY="`echo -n "$PKGNAME" | sed -e "$xPATTERN" -e 's%\-$%%'`"
     DB_pkgrelease="`echo -n "$pkg_name" | sed -e 's%.*\\-i[3456]86%%' -e 's%.*\\-noarch%%' -e 's%^\\-%%'`"
    ;;
    tar.gz)
     #arch ex: xproto-7.0.14-1-i686.pkg.tar.gz  trapproto-3.4.3-1.pkg.tar.gz
     PKGNAME="`echo -n "$pkg_name" | sed -e 's%\\-i[3456]86.*%%' -e 's%\\.pkg$%%' | rev | cut -f 2-9 -d '-' | rev`"
     DB_version="`echo -n "$PKGNAME" | grep -o '\\-[0-9].*' | sed -e 's%^\\-%%'`"
     xDB_version="`echo -n "$DB_version" | sed -e 's%\\-%\\\\-%g' -e 's%\\.%\\\\.%g'`"
     xPATTERN="s%${xDB_version}%%"
     PKGNAME_ONLY="`echo -n "$PKGNAME" | sed -e "$xPATTERN" -e 's%\\-$%%'`"
     DB_pkgrelease="`echo -n "$pkg_name" | sed -e 's%\\-i[3456]86.*%%' -e 's%\\.pkg$%%' | rev | cut -f 1 -d '-' | rev`"
    ;;
    rpm) #110523
     #exs: hunspell-fr-3.4-1.1.el6.noarch.rpm
     PKGNAME="$pkg_name"
     DB_version="`echo -n "$PKGNAME" | grep -o '\\-[0-9].*' | sed -e 's%^\-%%'`"
     xDB_version="`echo -n "$DB_version" | sed -e 's%\\-%\\\\-%g' -e 's%\\.%\\\\.%g'`"
     xPATTERN="s%${xDB_version}%%"
     PKGNAME_ONLY="`echo -n "$PKGNAME" | sed -e "$xPATTERN" -e 's%\\-$%%'`"
     DB_pkgrelease=""
    ;;
  esac
  [ "$PKGNAME_ONLY" != '' ] && echo $PKGNAME_ONLY || echo "$1"
}


get_pkg_name_only(){              # return pkg name only, no version or suffix FUNCLIST
  
  # exit if no valid options
  [ ! "$1" ] && exit 1
  
  # get config settings, inc current repo file
  #. ${PKGRC}
  
  local pkg_name=''
  local pkg_name_only=''
  local name_only=''
  local pkg_ext=`get_pkg_ext "$1"`
  local repo_of_pkg=''
  local repo_pkg_with_ext=''
  local repo_ext=$EX      # from $PKGRC

  # check the repos
  local pkg_name_only="`grep -m1 "|${1}|" ${HOME}/.packages/Packages-* | cut -f2 -d'|'`"
  [ "$pkg_name_only" = '' ] && pkg_name_only="`grep -m1 "^${1}|" ${HOME}/.packages/Packages-* | cut -f2 -d'|'`"
  [ "$pkg_name_only" = '' ] && pkg_name_only="`grep -m1 "|${1}.${pkg_ext}|" ${HOME}/.packages/Packages-* | cut -f2 -d'|'`"
  
  # if we found it, print it and exit
  if [ "$pkg_name_only" != '' ];then
      echo ${pkg_name_only}
      return 0
  fi
  
  # if not, but we have an extension, try  get_pkg_name_only_from_ext()
  case $DISTRO_BINARY_COMPAT in ubuntu|trisquel|debian|devuan)
    name_only=`get_pkg_name_only_from_ext "$(basename "${1}.${repo_ext}")"`
    [ "$name_only" != '' -a "$name_only" != "$1" ] && echo $name_only && return 0
    ;;
  esac
  
  ## ...if we didn't find the name using the above, do the horrible checks below
  
  # replace the dash before the version number with an @ symbol.
  # INFO: sed /-[^-][^+][^a-zA-Z][0-9.]*/ (hopefully?) replaces '-$VER' with '@' 
  # not including when $VER starts with a number/letter
  pkg_name_only="`echo "$(basename "${1}")" | sed -e 's/-[^-][^+][^a-zA-Z][0-9.]*/@/'`"

  # do 'ioquake3+u20130504' => 'oquake3'
  pkg_name_only="`echo "${pkg_name_only}" | sed -e 's/+[a-z]/@/'`"
  
  # note, we haven't cut away version numbers preceeded with underscores (_) yet
  
  # if the version number was preceeded by an underscore, the version 
  # will still be in the $pkg_name_only - pkgname_2.3.4 - so cut it out
  if [ "`echo "$pkg_name_only" | grep -o "_[0-9]\."`" != '' ];then
    pkg_name_only="`echo "$pkg_name_only" | sed -e 's/_[^a-z][^A-Z][0-9.]*/@/'`"

  # maybe the underscore preceeds a version that starts with a letter
  elif [ "`echo "$pkg_name_only" | grep -o "_[a-zA-Z][0-9]\."`" != '' ];then
    pkg_name_only="`echo "$pkg_name_only" | sed -e 's/_[a-zA-Z][0-9.]*/@/'`"
  fi
  
  # now cut away everything after the @, that will leave only the package name
  pkg_name_only1="${pkg_name_only/@*/}"
  pkg_name_only="$pkg_name_only1"

  # we might still have foo_bar_v1.2.3, so lets chop off * after the last _ 
  if [ "`echo "$pkg_name_only" | grep -o "_[a-zA-Z][0-9]\."`" != '' ];then
    pkg_name_only="${pkg_name_only/_[a-zA-Z][0-9]*/}"
  fi
  
  # another chop, we might have foo_bar_vv1.2.3, so lets chop off 
  # everything after the last underscore, if we still have version numbers
  if [ "`echo "$pkg_name_only" | grep -o "_[a-zA-Z][a-zA-Z][0-9]\."`" != '' ];then
    pkg_name_only="${pkg_name_only/_[a-zA-Z][a-zA-Z][0-9]*/}"
  fi
  
  # we might still have foo_bar_vvv1.2.3, so lets chop off 
  # everything after the last underscore, if we still have version numbers
  if [ "`echo "$pkg_name_only" | grep -o "_[a-zA-Z*][0-9]\."`" != '' ];then
    pkg_name_only="${pkg_name_only/_[a-zA-Z*][0-9]*/}"
  fi

  # chop again, we might have abc_xwy-zzz1.2.3-blah-etc, so lets chop off 
  # everything after the last dash-before-number
  if [ "`echo "$pkg_name_only" | grep -o "\-[a-zA-Z*]*[0-9]\."`" != '' ];then
    pkg_name_only="${pkg_name_only/-[a-zA-Z*]*[0-9]*/}"
  fi

  # another fix, if we still have PKGNAME-1.2, remove the '-1.2'
  if [ "`echo "$pkg_name_only" | grep -o "\-[0-9]"`" != '' ];then
    pkg_name_only="${pkg_name_only/-[0-9]*/}"
  fi

  # the sed bit changes 'liblzma5+20120614' to 'liblzma5'
  [ "$pkg_name_only" != '' ] && echo $pkg_name_only | sed -e 's/++/+++/g' -e 's/+[a-z0-9].*//g' || return 1
}


get_pkg_name(){                   # return pkg name with version FUNCLIST
  
  # get config settings, inc current repo file
  #. ${PKGRC}
  
  local pkg_ext=''
  local pkg_name=''
  local full_name=''
  local supported_repo_files=''
  local repo_contents=''
  
  # get the extension of the given package name, if any
  local pkg_ext=`get_pkg_ext "$1"`
  # get the name without path and extension
  local pkg_name="`basename "$1" .$pkg_ext`"
  
  # get the repos files in the correct (fall back) order, then add file paths
  supported_repo_files="`list_sources_files | sed -e "s#^#$HOME/.packages/#g"`"
  
  # get the relevant repo contents (fields 1,2,8) from all repos, 
  # then add pipes to line start/end for easier parsing later, then do 
  # a basic search, for $pkg* (we'll refine it later), to avoid 'Argument list too long'.. 
  cut -f1,2,8 $HOME/.packages/user-installed-packages $HOME/.packages/woof-installed-packages $supported_repo_files | sed -e "s/^/|/g" -e "s/$/|/g" 2>/dev/null | grep -i "|$pkg_name" > ${TMPDIR}repo_contents
  
  # get fields 1,2 and 8 (the 3 name fields) from all supported repo files, then 
  # add '|' to start and end of lines, then find exact match of $pkg_name.. 
  # if no exact match, look for $pkg_name-*, then $pkg_name_*
  if [ -f ${TMPDIR}repo_contents ];then
    full_name=`cat ${TMPDIR}repo_contents 2>/dev/null| grep -m1 "|${pkg_name}|"` \
      || full_name=`cat ${TMPDIR}repo_contents 2>/dev/null|grep -m1 "|${pkg_name//-*/}|"` \
      || full_name=`cat ${TMPDIR}repo_contents 2>/dev/null|grep -m1 "|${pkg_name//_*/}|"` \
      || full_name=`cat ${TMPDIR}repo_contents 2>/dev/null|grep -m1 "|${pkg_name}-"` \
      || full_name=`cat ${TMPDIR}repo_contents 2>/dev/null|grep -m1 "|${pkg_name}_"` \
      || full_name=`cat ${TMPDIR}repo_contents 2>/dev/null|grep -m1 "|${pkg_name}"` \
      || full_name=`cat ${TMPDIR}repo_contents 2>/dev/null|grep -m1 "^${pkg_name}|"` \
      || full_name=`cat ${TMPDIR}repo_contents 2>/dev/null|grep -m1 "^${pkg_name}-"` \
      || full_name=`cat ${TMPDIR}repo_contents 2>/dev/null|grep -m1 "^${pkg_name}_"`

    rm ${TMPDIR}repo_contents &>/dev/null
  fi

  # if we found pkg in repo, keep only the package name ('|pkg-123|pkg|blah|' -> 'pkg-123')
  [ "$full_name" != '' ] && full_name=`echo $full_name| cut -f2 -d '|' | tr -d '|'` || full_name=$pkg_name

  # if we have a package name, return it here and leave the func
  [ "$full_name" != '' ] && echo $full_name && return 0

  # if no pkg found in repos, we cant translate/lookup its longer name, 
  # so just return what we got, without path, without pkg extension
  [ "$full_name" = '' ] && echo "`basename "$pkg_name" .$pkg_ext`"
}


is_installed_pkg(){               # takes exact match of pkgname, prints true|false FUNCLIST
  
  # exit if no valid options
  [ ! "$1" -o "$1" = "-" ] && print_usage pkg-installed && exit 1
  
  local EX=''
  local PKGNAME=''
  local PKGNAME_ONLY=''
  local check=''
  
  # get pkg extension
  EX=`get_pkg_ext "$1"`
  
  # strip away extension and path
  PKGNAME="$(basename "$1" .$EX)"
  PKGNAME=`get_pkg_name "$PKGNAME"`

  # we cant rely on the strings the user passes us, so...
  
  # get the package name without version
  PKGNAME_ONLY=`get_pkg_name_only "$PKGNAME"` 

  # exit if no valid package name
  [ "$PKGNAME" = '' -o "$PKGNAME_ONLY" = '' ] && print_usage pkg-installed && exit 1

  # check the $HOME/.packages/*.files
  check="`find ${HOME}/.packages/ -name "$PKGNAME.files"`"
  [ "$check" = '' ] && check="`find ${HOME}/.packages/ -name "${PKGNAME}_*.files"`"
  [ "$check" = '' ] && check="`find ${HOME}/.packages/ -name "${PKGNAME}-*.files"`"
  [ "$check" = '' ] && check="`find ${HOME}/.packages/ -name "${PKGNAME}*.files"`"

  # slow but reliable & simple: separately check fields 1,2,8 of the various files listing installed pkgs
  [ "$check" = '' ] && check="`cut -f1 -d'|' ${HOME}/.packages/*-installed-packages 2>/dev/null| grep -m1 "^$PKGNAME\$"`"
  [ "$check" = '' ] && check="`cut -f1,2 -d'|' ${HOME}/.packages/*-installed-packages 2>/dev/null| grep -m1 "^$PKGNAME|" | grep -m1 "|$PKGNAME_ONLY\$"`"
  [ "$check" = '' ] && check="`cut -f8 -d'|' ${HOME}/.packages/*-installed-packages 2>/dev/null| grep -m1 "^$PKGNAME"`"
  [ "$check" = '' ] && check="`HIDE_BUILTINS=false list_installed_pkgs | grep -m1 ^"$PKGNAME"`"
  
  # if any checks above returned a result, $check will not be empty (ash didn't like grep -q, not sure why?)
  [ "$check" != '' ] && echo true && return 0 # pkg is installed
  
  # if we made it here, the given pkg is not installed
  echo false
  exit 1

}


is_builtin_pkg (){                # return true if pkg is builtin, else false FUNCLIST
  
  # if $1 is an exact match of a pkg short name, 
  # long name or file name in woof-installed-packages, 
  # we will return true, else we return false

  # exit if no valid input
  [ ! "$1"  ] && exit 1
  
  local pkg_builtin=''
  local pkg_name_only=''

  pkg_builtin="`cat ${HOME}/.packages/woof-installed-packages 2>/dev/null\
    | cut -f1,2,8 -d '|' \
    | sed -e 's@^@|@' -e 's@$@|@' \
    | grep -m1 "|$1|"`"
  
  # try again.. if user gave only partial name (geany-1.27), the above would fail
  if [ "$pkg_builtin" = '' ];then
    pkg_name_only=`get_pkg_name_only "$1"`
    
    # so search for pkg_name* AND pkg_name_only (exact match, should be in field 2)
    if [ "$pkg_name_only" != '' ];then
      pkg_builtin="`cat ${HOME}/.packages/woof-installed-packages 2>/dev/null\
        | cut -f1,2,8 -d '|' \
        | sed -e 's@^@|@' -e 's@$@|@' \
        | grep "|$1" \
        | grep -m1 "|$pkg_name_only|"`"
    fi
  fi

  # print result
  [ "$pkg_builtin" != '' ] && echo true || echo false
}


is_devx_pkg (){                   # return true if pkg is in the devx, else false FUNCLIST
  
  # if $1 is an exact match of a pkg short name, 
  # long name or file name in devx-only-installed-packages, 
  # we will return true, else we return false

  # exit if no valid input
  [ ! "$1"  ] && exit 1
  
  local devx_pkg=''
  local pkg_name_only=''

  devx_pkg="`cat ${HOME}/.packages/devx-only-installed-packages 2>/dev/null\
    | cut -f1,2,8 -d '|' \
    | sed -e 's@^@|@' -e 's@$@|@' \
    | grep -m1 "|$1|"`"
  
  # try again.. if user gave only partial name (geany-1.27), the above would fail
  if [ "$devx_pkg" = '' ];then
    pkg_name_only=`get_pkg_name_only "$1"`
    
    # so search for pkg_name* AND |pkg_name_only| (exact match, should be in field 2)
    if [ "$pkg_name_only" != '' ];then
      devx_pkg="`cat ${HOME}/.packages/devx-only-installed-packages 2>/dev/null\
        | cut -f1,2,8 -d '|' \
        | sed -e 's@^@|@' -e 's@$@|@' \
        | grep "|$1" \
        | grep -m1 "|$pkg_name_only|"`"
    fi
  fi
  
  # print result
  [ "$devx_pkg" != '' ] && echo true || echo false
}


is_usr_pkg (){                    # return true if pkg is user installed, else false FUNCLIST
  
  # if $1 is an exact match of a pkg short name, 
  # long name or file name in user-installed-packages, 
  # we will return true, else we return false

  # exit if no valid input
  [ ! "$1"  ] && exit 1
  
  local usr_pkg=''
  local pkg_name_only=''
  
  usr_pkg="`cat ${HOME}/.packages/user-installed-packages 2>/dev/null\
    | cut -f1,2,8 -d '|' \
    | sed -e 's@^@|@' -e 's@$@|@' \
    | grep -m1 "|$1|"`"
  
  # try again.. if user gave only partial name (geany-1.27), the above would fail
  if [ "$usr_pkg" = '' ];then
    pkg_name_only=`get_pkg_name_only "$1"`
    
    # so search for pkg_name* AND |pkg_name_only| (exact match, should be in field 2)
    if [ "$pkg_name_only" != '' ];then
      usr_pkg="`cat ${HOME}/.packages/user-installed-packages 2>/dev/null\
        | cut -f1,2,8 -d '|' \
        | sed -e 's@^@|@' -e 's@$@|@' \
        | grep "|$1" \
        | grep -m1 "|$pkg_name_only|"`"
    fi
  fi
  
  # print result
  [ "$usr_pkg" != '' ] && echo true || echo false
}


is_repo_pkg (){                   # return true if pkg is in supported repo, else false FUNCLIST
  
  # if $1 is an exact match of a pkg short name, 
  # long name or file name in Packages-*-
  # we will return true, else we return false

  # exit if no valid input
  [ ! "$1"  ] && exit 1
  
  local repo_pkg=''
  local pkg_name_only=''
  local all_supported_repofiles
  
  # all repo files, full paths
  all_supported_repofiles=`list_sources_files | sed "s#^#$HOME/.packages/#" | tr '\n' ' '`

  # search all repo files for the $1
  repo_pkg="`cat $all_supported_repofiles 2>/dev/null\
    | cut -f1,2,8 -d '|' \
    | sed -e 's/ //g' -e 's@^@|@' -e 's@$@|@' \
    | grep -m1 "|${1}|"`"
    
  # search all repo files for the $1*
  [ "$repo_pkg" = '' ] \
    && repo_pkg="`cat $all_supported_repofiles 2>/dev/null\
    | cut -f1,2,8 -d '|' \
    | sed -e 's/ //g' -e 's@^@|@' -e 's@$@|@' \
    | grep -m1 "|${1}-\?_\?[0-9.a-zA-Z]*|"`"
  
  # try again.. if user gave only partial name (geany-1.27), the above would fail
  if [ "$repo_pkg" = '' ];then
    pkg_name_only=`get_pkg_name_only "$1"`
    
    # so search for pkg_name* AND |pkg_name_only| (exact match, should be in field 2)
    if [ "$pkg_name_only" != '' ];then
      repo_pkg="`cat $all_supported_repofiles 2>/dev/null\
        | cut -f1,2,8 -d '|' \
        | sed -e 's@^@|@' -e 's@$@|@' \
        | grep "|$1" \
        | grep -m1 "|$pkg_name_only|"`"
    fi
  fi
  
  # print result
  [ "$repo_pkg" != '' ] && echo true || echo false
}


is_current_repo_pkg(){            # takes $PKGNAME, returns true or false FUNCLIST
  
  # exit if no valid input
  [ ! "$1"  ] && exit 1
  
  # get current repo ($REPOFILE)
  . ${PKGRC}
  
  local pkg_in_repo
  
  # check if given pkg ($1) is in the current repo
  pkg_in_repo="`LANG=C cut -f1,2,7,8 -d'|' ${HOME}/.packages/$REPOFILE 2>/dev/null | sed -e "s/^/|/" -e "s/$/|/" | grep -m1 "|${1}|"`"
  
  # print msg
  [ "$pkg_in_repo" != '' ] && echo true || echo false
}


is_local_pkg(){                   # returns true if $1 is local package file FUNCLIST

  # exit if no valid input
  [ ! "$1"  ] && exit 1
  
  . ${PKGRC}
  
  # if $1 is a local file with a supported package extension
  # then we return true, else, we return false

  local is_file=''
  local is_local_pkg=false

  # first, check we have a local file
  if [ -f "$1" ];then
  
    # file *probably* has an extension, lets try to get it..
    # the func get_pkg_ext() will return empty if not a valid package extension
    file_ext=`get_pkg_ext "$1"`
    
    # if not empty, it must be a local file, with valid pkg ext (a local pkg)
    [ "$file_ext" != '' ] && is_local_pkg=true
  
  elif [ -f "$CURDIR/$1" ];then
    
    file_ext=`get_pkg_ext "$CURDIR/$1"`
    [ "$file_ext" != '' ] && is_local_pkg=true

  elif [ -f "$WORKDIR/$1" ];then
    
    file_ext=`get_pkg_ext "$CURDIR/$1"`
    [ "$file_ext" != '' ] && is_local_pkg=true
  
  fi
  
  # print output
  echo $is_local_pkg
}


# RC file funcs

set_workdir(){                    # set new WORKDIR in rc file location FUNCLIST
  
  # get latest rc file values
  . ${PKGRC}
  
  # make sure $1 was given and doesn't already exist
  [ ! "$1"  ] && print_usage workdir && exit 1
  [ -e "$1" ] && echo "Error: directory already exists. Choose a new one." && exit 1
  
  # create the dir
  mkdir -p "$1" 2>/dev/null
  
  # if dir not created, exit with error
  [ $? -eq 1  ] && echo "Error: Could not create $1" && exit 1
  [ ! -d "$1" ] && echo "Error: Could not create directory:  $1" && exit 1
  
  # dir was created, so lets copy our pkgs in there
  list_downloaded_pkgs | while read pkg_file
  do
    cp -v "$WORKDIR/$pkg_name" "$1/"
  done
  
  # if copying everything to new dir failed
  if [ $? -eq 1 ];then
    # print msg
    echo -e "${yellow}Warning:${endcolour}Could not copy packages from $WORKDIR to $1.."
    echo "You should copy all packages in $WORKDIR into $1."
  fi

  # update the RC file
  WORKDIR="$1"
  export WORKDIR
  set_config
  echo "Success. Work directory updated."
  exit 0
}


set_pkg_scope(){                  # one|all set search for pkgs in current repo or all FUNCLIST
  
  # get old values, any we dont set here are not overwritten
  . ${PKGRC} 
  
  [ "$1" != "" ] && PKGSCOPE="$1" || PKGSCOPE="$PKGSCOPE"
  
  case "$1" in 
    all)
    # set pkg search to all
    PKGSEARCH="list_all_pkg_names"
    PKGSEARCHEXACT="$SELF -nea"
    echo -e "${green}Success:${endcolour} Find packages in all repos."
    ;;
    one)
    # set pkg search to current only
    PKGSEARCH="list_pkg_names"
    PKGSEARCHEXACT="$SELF -ne"
    echo -e "${green}Success:${endcolour} Find packages in current repo ($REPONAME) only."
    ;;
    *)
    PKGSCOPE="one"
    # set pkg search to current only
    PKGSEARCH="list_pkg_names"
    PKGSEARCHEXACT="$SELF -ne"
    echo "Find packages in current repo ($REPONAME) only."
    ;;
  esac
  
  set_config #170213
}


set_dep_scope(){                  # all|one set search for deps in current repo or all FUNCLIST
  
   # get RC file values, so any we dont set here are not overwritten
   . ${PKGRC}

  # make sure we have a valid value
  [ "$1" != "" ] && DEPSCOPE="$1" || DEPSCOPE="$DEPSCOPE"
  
  case "$1" in 
    all)
    # set pkg search to all
    DEPSEARCH="list_all_pkg_names"
    DEPSEARCHEXACT="$SELF -nea"
    echo -e "${green}Success:${endcolour} Find dependencies in all repos."
    ;;
    one)
    # set pkg search to one
    DEPSEARCH="list_pkg_names"
    DEPSEARCHEXACT="$SELF -ne"
    echo -e "${green}Success:${endcolour} Find dependencies in current repo ($REPONAME) only."
    ;;
  esac
  
  set_config
}


set_recursive_deps(){             # yes|no search for deps of deps or not FUNCLIST
  [ "`echo $1 | grep -E "^yes\$|^no\$"`" = "" ] && print_usage recursive-dep-check && exit 1
  
  # get old values, any we dont set here are not overwritten
  . ${PKGRC} 
  
  # make sure we have a valid value
  RDCHECK="$1"
  [ "$RDCHECK" = "yes" -o "$RDCHECK" = "no" ] || RDCHECK=no
  
  set_config
  
  # print final msg
  if [ "$1" = "yes" ];then
    echo -e "${green}Success:${endcolour} 'Recursive dependency checking' enabled."
  else
    echo -e "${green}Success:${endcolour} 'Recursive dependency checking' disabled"
  fi
}


set_bleeding_edge(){              # yes|no get latest pkgs, ignore fall backs FUNCLIST
  [ "`echo $1 | grep -E "^yes\$|^no\$"`" = "" ] && echo usage bleeding-edge && exit 1
  
  #get old values, any we dont set here are not overwritten
  . ${PKGRC} 
  
  # make sure we have a valid value
  BLEDGE="$1"
  [ "$BLEDGE" = "yes" -o "$BLEDGE" = "no" ] || BLEDGE=no
  
  set_config
  
  # print final msg
  if [ "$1" = "yes" ];then
    echo -e "${green}Success:${endcolour} 'Bleeding edge' package search enabled."
  else
    echo -e "${green}Success:${endcolour} 'Bleeding edge' package search disabled."
  fi
}


set_autoclean(){                  # yes|no auto delete installed packages from WORKDIR FUNCLIST
  [ "`echo $1 | grep -E "^yes\$|^no\$"`" = "" ] && print_usage autoclean && exit 1
  
  #get old values, any we dont set here are not overwritten
  . ${PKGRC} 
  
  # make sure we have a valid value
  AUTOCLEAN="$1"
  [ "$AUTOCLEAN" = "yes" -o "$AUTOCLEAN" = "no" ] || AUTOCLEAN=no
  
  set_config
  
  # print final msg
  if [ "$1" = "yes" ];then
    echo -e "${green}Success:${endcolour} Auto-remove installed packages ENABLED."
  else
    echo -e "${green}Success:${endcolour} Auto-remove installed packages DISABLED."
  fi
}


set_config(){                     # update all options in config file FUNCLIST
  echo "WORKDIR=$WORKDIR"            > ${PKGRC}
  echo "REPONAME=$REPONAME"           >> ${PKGRC}
  echo "EX=$EX"                 >> ${PKGRC}
  echo "REPOFILE=$REPOFILE"           >> ${PKGRC}
  echo "REPOURL1=$REPOURL1"           >> ${PKGRC}
  echo "REPOURL2=$REPOURL2"           >> ${PKGRC}
  #140213 add all urls
  echo "REPOURL3=$REPOURL3"           >> ${PKGRC}
  echo "REPOURL4=$REPOURL4"           >> ${PKGRC}
  # seach settings
  echo "PKGSEARCH=\"$PKGSEARCH\""       >> ${PKGRC}
  echo "PKGSEARCHEXACT=\"$PKGSEARCHEXACT\"" >> ${PKGRC}
  echo "DEPSEARCH=\"$DEPSEARCH\""       >> ${PKGRC}
  echo "DEPSEARCHEXACT=\"$DEPSEARCHEXACT\"" >> ${PKGRC}
  # multiple repo settings
  echo "REPOFALLBACKS=\"$REPOFALLBACKS\""   >> ${PKGRC}
  echo "PKGSCOPE=\"$PKGSCOPE\""         >> ${PKGRC}
  echo "DEPSCOPE=\"$DEPSCOPE\""         >> ${PKGRC}
  echo "BLEDGE=\"$BLEDGE\""           >> ${PKGRC}
  echo "RDCHECK=\"$RDCHECK\""         >> ${PKGRC} #150813
  echo "AUTOCLEAN=\"$AUTOCLEAN\""         >> ${PKGRC}
  echo "BUILDTOOL=$BUILDTOOL"         >> ${PKGRC}
}


show_config(){                    # show config settings from ~/.pkg/pkgrc FUNCLIST
  . ${PKGRC}
  
  # set default values
  PKGSCOPETXT="Search for packages in all repos."
  DEPSCOPETXT="Search for dependencies in all repos."
  FALLBACKTXT="Accessing other repos in this order:"
  FALLBACKTXT="$FALLBACKTXT\n`repo_list | grep -v "^$REPONAME" | tr '\n' ' ' | sed -e "s/ /, /g" -e "s/, $//" | fold -w 54 -s`"
  RDCHECKTXT="Recursive dependency search is NOT enabled."

  # update with values from PKGRC file
  [ "$PKGSCOPE" = "one" ] && PKGSCOPETXT="Search for packages in current repo only." 
  [ "$DEPSCOPE" = "one" ] && DEPSCOPETXT="Search for dependencies in current repo only."
  [ "$BLEDGE"   = "yes" ] && FALLBACKTXT="Bleeding-edge enabled - searching all repos, for the latest packages versions.."
  [ "$RDCHECK"  = "yes" ] && RDCHECKTXT="Recursive dependency search is enabled."

  # print current Pkg config
  echo "==========================="
  echo "$APPNAME $APPVER"
  echo "==========================="
  echo "Config file:  $PKGRC"
  echo "Packages dir: ${WORKDIR}/"
  echo "Autoclean:    $AUTOCLEAN"
  echo 
  echo "Search settings:"
  #echo "- $HIDEINSTALLEDTXT"
  echo "- $PKGSCOPETXT"
  echo "- $DEPSCOPETXT"
  echo "- $RDCHECKTXT"
  echo 
  echo "Package Compiling backend:"
  echo "- $BUILDTOOL"
  echo 
  echo "Repo details:"
  echo "- Current Repo: $REPONAME"
  echo "- Package type: $EX"
  echo "- Packages:     `cat ${HOME}/.packages/${REPOFILE} | wc -l`"
  echo "- Mirror 1:     `echo $REPOURL1 | cut -f1-3 -d'/' `"
  [ "$REPOURL2" != "" ] && echo "- Mirror 2:     `echo $REPOURL2 | cut -f1-3 -d'/' `"
  [ "$REPOURL3" != "" ] && echo "- Mirror 3:     `echo $REPOURL3 | cut -f1-3 -d'/' `"
  [ "$REPOURL4" != "" ] && echo "- Mirror 4:     `echo $REPOURL4 | cut -f1-3 -d'/' `"
  echo
  echo -e "$FALLBACKTXT"
}


# repo and source funcs

get_repo_info(){                  # return details of given repo name FUNCLIST
  [ ! "$1" -o "$1" = "-" ] && print_usage repo-info && exit 1
  export REPOLINE="`list_all_sources $1`" #170214 always get latest info, not info from rcfile

  # on first run, this might be needed to se the repo correctly
  [ "$REPOLINE" = '' ] && export REPOLINE="`list_all_sources noarch`"

  export REPONAME="`echo $REPOLINE | cut -f1 -d'|'`"
  export       EX="`echo $REPOLINE | cut -f2 -d'|'`"
  export REPOFILE="`echo $REPOLINE | cut -f3 -d'|'`"
  export REPOURL1="`echo $REPOLINE | cut -f4 -d'|'`"
  export REPOURL2="`echo $REPOLINE | cut -f5 -d'|'`"
  export REPOURL3="`echo $REPOLINE | cut -f6 -d'|'`"
  export REPOURL4="`echo $REPOLINE | cut -f7 -d'|'`"
  export REPOFALLBACKS="`echo "$REPOLINE"| cut -f8 -d'|'`"
}


set_current_repo(){               # set the current default repo FUNCLIST
  
  # print usage if no valid options
  [ ! "$1" -o "$1" = "-" ] && print_usage repo && exit 1
  
  # get repo details from rc file
  . ${PKGRC}
  
  # remove the default mirror tmp file, we're changing repo and mirrors
  rm $TMPDIR/CURREPOURL 2>/dev/null

  # remove old repo files list (used in list_source_files)
  rm -f ${TMPDIR}source_files 2>/dev/null

  # if not updating the scopes or bleeding-edge,leave them as set in rcfile
  [ "$PKGSCOPE" = "" ] && PKGSCOPE="$PKGSCOPE"
  [ "$DEPSCOPE" = "" ] && DEPSCOPE="$DEPSCOPE"
  [ "$BLEDGE" = "" ]   && BLEDGE="$BLEDGE"

  # if nothing was found in rcfile, we need to set to default
  [ "`echo $PKGSCOPE | grep -E "^one\$|^all\$"`" = "" ] && PKGSCOPE="one"
  [ "`echo $DEPSCOPE | grep -E "^one\$|^all\$"`" = "" ] && DEPSCOPE="one"
  [ "$BLEDGE" = "" ] && BLEDGE="no"

  # check if $1 is valid repo
  if [ "$(LANG=C list_sources "$1")" != "" ];then
    # set repo details
    LANG=C get_repo_info "$1"
    LANG=C set_config #170213
    LANG=C update_sources 1>/dev/null #update the order of sources to match new fallback list of new current repo
    LANG=C print_repo_info "$1" #output msg, repo info
  else
    # not a valid repo, print message
    echo "The name '$1' is not a valid repo name. These are:"
    LANG=C repo_list #250613
  fi
}


repo_list(){                      # list names of all avail repos FUNCLIST
  
  # we need to list these repos in the order defined in the RC file
  # so Pkg can 'fall back' to other repos in that order
  
  # get current config
  . ${PKGRC}
  
  # set vars for this func
  local list=''
  local repo_file=''
  local repo_names=`cut -f1 -d'|' ${HOME}/.pkg/sources`
  local current_fallback_list=`grep "^$REPONAME|" ${HOME}/.pkg/sources | cut -f8 -d'|' | grep -v "^\$"`
  
  # get current repo fallback list order.. note if repo not listed in fallback list, it will be appended after
  for line in $current_fallback_list
  do
    # get the repo file
    repo_file="`grep "^$LINE|" ${HOME}/.pkg/sources | cut -f3 -d'|'`"
    # add it to the list
    [ "$repo_file" != "" ] && list="$list$line "
  done

  # add space at end to help search in for loop below
  line="$line " 

  # now add all other avail repos to the end of fallback list
  for repo_name in $repo_names
  do
    #if not blank, not already in the repo list and not the current repo ($REPONAME from rc file) then add to list
    [ "$repo_name" != "" -a "`echo "$list" | grep "$repo_name "`" = ""  -a "$repo_name" != "$REPONAME" ] && list="$list$repo_name "
  done
  
  # list the current repo first
  echo $REPONAME
  # then the other repos
  echo "$list" | tr ' ' '\n' | grep -v "^\$" 
}


repo_file_list(){                 # list available repo files, $1 optional FUNCLIST
  local file_list
  file_list="`cat ${HOME}/.pkg/sources | grep "^$1|"| cut -f3 -d'|'`"
  [ "$file_list" = ''  ] && file_list="`cat ${HOME}/.pkg/sources | grep "^$1"| cut -f3 -d'|'`"
  [ "$file_list" != '' ] && echo "$file_list"
}


list_sources(){                   # return available (matching) repos (~/.pkg/sources) FUNCLIST
  grep -m1 "^$1" ${HOME}/.pkg/sources #160213
}


list_all_sources(){               # return all (or matching) repos (~/.pkg/sources-all) FUNCLIST
  grep -m1 "^$1" ${HOME}/.pkg/sources-all #160213
}


list_sources_files(){             # list repo files of all available repos FUNCLIST
  # get the specific ordering of our supported repos from the config
  . ${PKGRC}
  
  [ -f ${TMPDIR}source_files ] && cat ${TMPDIR}source_files && return 0

  local repos_list
  local FALLBACKS="`grep "^$REPONAME|" ${HOME}/.pkg/sources | cut -f8 -d'|' `"

  # add current repo to list, then all repos it falls back to 
  repos_list="$REPONAME $FALLBACKS"
  # now add all other repos, sort, remove duplicates
  repos_list="$RL `echo $(repo_list)`"| sort | uniq

  # for each repo available  
  for R in $repos_list
  do
    # get the repo file name for sources-all
    RF="`grep "^$R|" ${HOME}/.pkg/sources-all | cut -f3 -d'|'`"
    # if repo file is valid, echo to stdout
    [ "$RF" != "" -a -f "$HOME/.packages/$RF" ] && echo $RF >> ${TMPDIR}source_files
  done

  cat ${TMPDIR}source_files
}


add_source(){                     # add a new repo to your repo 'sources' list FUNCLIST
  [ ! "$1" \
    -o "$1" = "-" \
    -o "`echo "$1" |  grep '|'`" = "" \
    -o "`echo "$1" | cut -f2 -d'|'`" = "" \
    -o "`echo "$1" | cut -f4 -d'|'`" = "" \
    -o "`echo "$1" | cut -f8 -d'|'`" = "" ] && \
    print_usage add_source && exit 1

  # get repo file to add to sources
  REPOTOADD="`echo $1 | cut -f1 -d'|'`"
  REPOFILETOADD="`echo $1 | cut -f3 -d'|'`"
  
  # do checks before adding repo (dont add duplicate, make sure file exists, etc)
  
  # check if repo name already in sources-all
  [ "`grep "^$REPOTOADD\$" ~/.pkg/sources-all`" != "" ]  && echo "Repo with the name '$REPOTOADD' already in the list" && exit 1
  # check if repo already in our repo list 
  [ "`repo_list | grep "^$REPOTOADD\$"`" != "" ] && echo "Repo with the name '$REPOTOADD' already in the list" && exit 1
  # check if repo filename already  exists in sources-all
  [ "`repo_file_list | grep "^$REPOFILETOADD\$"`" != "" ]    && echo "Repo with database file $HOME/.packages/'$REPOFILETOADD' already in the list" && exit 1
  # check if the repo file exists in $HOME/.packages
  [ ! -f "`find $HOME/.packages/ -name "$REPOFILETOADD"`" ] && echo "The repo database file '$HOME/.packages/$REPOFILETOADD' not found." && exit 1
  
  # all good, so add repo entry to sources-all
  echo "$1" >> ${HOME}/.pkg/sources-all
  echo ""   >> ${HOME}/.pkg/sources-all
  
  # update users repo sources to get the new repo
  update_sources 1>/dev/null || { echo "Could not update repo sources."; exit 2; }
  
  # print msg
  echo "Repo '$REPOTOADD' added successfully."
}


update_sources(){                 # create the list of available repos FUNCLIST
  
  # get current repo values and Pkg settings
  . ${PKGRC}
  
  #list current repo first in sources
  get_repo_info "${REPONAME:-noarch}"
  
  
  # only add the current repo to the list of available sources if it exists
  if [ "`find $HOME/.packages/ -iname "$REPOFILE" `" != '' ];then
    echo "$REPONAME|$EX|$REPOFILE|$REPOURL1|$REPOURL2|$REPOURL3|$REPOURL4|$REPOFALLBACKS" > ${HOME}/.pkg/sources
  fi

  # get repos in order of fallbacks, pkg will then 'fall back' to each repo in that order
  FALLBACKS="`grep "$REPONAME" ${HOME}/.pkg/sources-all 2>/dev/null | grep -v ^'#' | cut -f8 -d'|'`"
  
  # for each repo in fallback list
  for FBACK in $REPOFALLBACKS; do
    # dont add current repo, its already added
    [ "$FBACK" = "$REPONAME" ] && continue 
    # check if repo is supported (has entries in sources-all)
    LINE="`grep "$FBACK|" ${HOME}/.pkg/sources-all 2>/dev/null | grep -v ^'#' | grep -v "^$REPONAME"`" #160213
    [ "$LINE" = "" ] && continue
    # if repo is valid, add to users list of in-use repos (only valid repos from sources-all => sources)
    if [ -f "${HOME}/.packages/`echo "$LINE" | cut -f3 -d'|'`" ];then
      echo "Adding repo: `echo "$LINE"|cut -f1 -d'|'`.."
      echo "$LINE" >> ${HOME}/.pkg/sources
    fi
  done

  cleaned_repo_list="`cat ${HOME}/.pkg/sources-all 2>/dev/null | grep -v ^'#'`"
  
  # now add any other repos to the list (repos that are installed, but not added from fallback list)
  echo "$cleaned_repo_list" | while read repo_entry
  do
    # dont add current repo, its already added
    [ "`echo "$repo_entry" | cut -f1 -d'|'`" = "$REPONAME" ] && echo "Adding repo: $REPONAME.." && continue
    
    # get the repo name
    repo_name=`echo "$repo_entry"|cut -f1 -d'|'`

    # build the repo file (full path)
    repo_file=${HOME}/.packages/`echo "$repo_entry" | cut -f3 -d'|'`
    
    # set a flag true if repo already in repo, false if not
    already_in_repo=false
    [ "`grep -m1 "^$repo_entry" ${HOME}/.pkg/sources 2>/dev/null`" ] && already_in_repo=true
    
    if [ -f "$repo_file" -a "$already_in_repo" = false ];then
      echo "Adding repo: $repo_name.."
      echo "$repo_entry" >> ${HOME}/.pkg/sources
    fi
  done
  
  # finished, print message
  [ -f ${HOME}/.pkg/sources ] && echo "Sources updated." && . ${PKGRC}
}


update_repo(){                    # update the current repo from a file stored online FUNCLIST
  
  # check internet, net connection required
  NET="`check_net`"; [ $NET -eq 1 ] && echo "You need an internet connection" && exit 1

  # remove the repo update tmp file
  rm -f $TMPDIR/update_repo_results 2>/dev/null

  echo "Updating repositories.. Please wait."

  # use petget for now .. not ideal, petget wont accept $1 and only do that repo, 
  # also petget uses loads of other files pkg doesnt have/need (in $HOME/.packages)
  # also, we're limited to updating only the repos that petget supports, not all the ones Pkg supports..
  # .. on the plus side petget code is way faster than mine
  mkdir -p /var/local/petget/
  chmod 777 /var/local/petget/
  echo 'false' > /var/local/petget/db_verbose
  
  # now call petget 0setup.. the ENV options prevent popup windows, and need for user input 
  DISPLAY='' SETUPCALLEDFROM=ppm /usr/local/petget/0setup &>$TMPDIR/update_repo_results
  
  # if the repos updated ok
  if [ $? -eq 0 ];then
    [ "`which logger`" != '' ] && logger "$0 Repo files updated by $APP $APPVER"
    echo -e "Repo files updated:"
    grep ^Processing $TMPDIR/update_repo_results | cut -f2 -d' '
    # remove the repo update tmp file
    rm -f $TMPDIR/update_repo_results 2>/dev/null
    exit 0
  else
    # repo did not update ok
    error "Repos NOT updated."
    cat $TMPDIR/update_repo_results | tail -20
    exit 2
  fi
}


convert_repofile(){               # convert repo files formats (pre-woof/post-woof) FUNCLIST
  
  # get the file name (FILENAME) and full path (FILE)
  FILENAME="`basename "$1"`"
  FILE="${CURDIR}/${FILENAME}"
  
  # check for valid options
  [ ! -f "$FILE" ] && print_usage repo-convert && exit 1

  # dont replace repo unless -f was given
  [ "$FORCE" != true -a -f "${HOME}/.packages/${FILENAME}" ] && echo "File '${HOME}/.packages/$FILENAME' already exists."  && exit 1
  
  # remove tmp files
  rm $TMPDIR/$FILENAME &>/dev/null
  rm $TMPDIR/${FILENAME}_subdirs &>/dev/null
  
  # check repo file format (woof or pre-woof)
  if [ -f "$FILE" -a "`cat "$FILE" | head -1 | grep -m1 '^"'`" = "" ];then #if is a new format  #'
    
    # convert woof repo file to pre-woof repo file.. takes ages..
    echo "Converting '${FILE}' to pre-woof format.. This might take a while.."
    cat "$FILE" | while read LINE
    do
      PKGNAME="`echo $LINE| cut -f1 -d'|'`"
      PKGNAME1=''
      # we need to get the package name, try lots of different extensions
      [ "`echo $PKGNAME1 | grep ".deb\$"`" != "" ]  && PKGNAME1="`echo $LINE| cut -f8 -d'|'`"
      [ "`echo $PKGNAME1 | grep ".deb\$"`" != "" ]  && PKGNAME="`basename $PKGNAME1 .deb`"
      [ "`echo $PKGNAME1 | grep ".rpm\$"`" != "" ]  && PKGNAME="`basename $PKGNAME1 .rpm`"
      [ "`echo $PKGNAME1 | grep ".txz\$"`" != "" ]  && PKGNAME="`basename $PKGNAME1 .txz`"
      [ "`echo $PKGNAME1 | grep ".tgz\$"`" != "" ]  && PKGNAME="`basename $PKGNAME1 .tgz`"
      [ "`echo $PKGNAME1 | grep ".tar.xz\$"`" != "" ] && PKGNAME="`basename $PKGNAME1 .tar.xz`"
      [ "`echo $PKGNAME1 | grep ".tar.gz\$"`" != "" ] && PKGNAME="`basename $PKGNAME1 .tar.gz`"
      # get size
      SIZE=" `echo $LINE| cut -f6 -d'|'`"
      # get category
      CAT="`echo $LINE| cut -f5 -d'|'`"
      #150813 remove extra categories .. example 'Setup;Installation' .. remove 'Installation'
      [ "`echo "$CAT" | grep ';'`" != "" ] && CAT="`echo "$CAT" | cut -f1 -d';'`"
      # get sub dir in repo
      SUBDIR="`echo $LINE| cut -f7 -d'|'`" #150213
      # get deps
      DEPS=" `echo $LINE| cut -f9 -d'|'| grep '+'`"
      # get desc
      DESC="`echo $LINE| cut -f10 -d'|'`"
      # add repo entry to tmp file
      [ "$PKGNAME" != "" ] && echo "\"$PKGNAME\" \"$PKGNAME: ${DESC//:/,}\" off \"$CAT$DEPS$SIZE\" /" | sed -e 's/  / /g' -e 's/,,/,/g' -e 's/, ,/,/g' | sort --field-separator='-' -k1,1d -k2gr -k3gr -k4gr | uniq >> $TMPDIR/$FILENAME
      #150213 now do subdirs... slow..
      [ "`echo $SUBDIR | grep "/"`" != "" -a "`echo $SUBDIR | grep -i pet_packages`" = "" ] && echo "$PKGNAME|/$SUBDIR" >> $TMPDIR/${FILENAME}_subdirs
    done
    # done making a pre-woof repo file, print message
    [ -f $TMPDIR/$FILENAME ] && echo "Finished converting $FILENAME to pre-woof format." || exit 1
  
  else
    
    # convert pre-woof repo file to woof repo file.. takes ages..
    echo "Converting '$FILENAME' to a 'woof' compatible repo file. This could take a while..."
    
    # parse a pre-woof repo file
    cat "$FILE" | while read LINE
    do
      PKGNAME='' PKGNAMEONLY='' PKGVER='' SIZE='' CAT='' DEPS='' BUILD='' SUBDIR='' PKGEXT='.pet' DESC=''

      PKGNAME="`echo "$LINE" | cut -d'"' -f2`"
      [ "`echo $PKGNAME | grep ".deb\$"`" != "" ]     && PKGEXT='.deb'    && PKGNAME="`basename $PKGNAME1 .deb`"
      [ "`echo $PKGNAME | grep ".pet\$"`" != "" ]     && PKGEXT='.pet'    && PKGNAME="`basename $PKGNAME1 .pet`"
      [ "`echo $PKGNAME | grep ".rpm\$"`" != "" ]     && PKGEXT='.rpm'    && PKGNAME="`basename $PKGNAME1 .rpm`"
      [ "`echo $PKGNAME | grep ".tcz\$"`" != "" ]     && PKGEXT='.tcz'    && PKGNAME="`basename $PKGNAME1 .tcz`"
      [ "`echo $PKGNAME | grep ".tgz\$"`" != "" ]     && PKGEXT='.tgz'    && PKGNAME="`basename $PKGNAME1 .tgz`"
      [ "`echo $PKGNAME | grep ".txz\$"`" != "" ]     && PKGEXT='.txz'    && PKGNAME="`basename $PKGNAME1 .txz`"
      [ "`echo $PKGNAME | grep ".tar.gz\$"`" != "" ]    && PKGEXT='.tar.gz'   && PKGNAME="`basename $PKGNAME1 .tar.gz`"
      [ "`echo $PKGNAME | grep ".tar.xz\$"`" != "" ]    && PKGEXT='.tar.xz'   && PKGNAME="`basename $PKGNAME1 .tar.xz`"
      [ "`echo $PKGNAME | grep ".pkg.tar.gz\$"`" != "" ]  && PKGEXT='.pkg.tar.gz' && PKGNAME="`basename $PKGNAME1 .pkg.tar.gz`"
      [ "`echo $PKGNAME | grep ".pkg.tar.xz\$"`" != "" ]  && PKGEXT='.pkg.tar.xz' && PKGNAME="`basename $PKGNAME1 .pkg.tar.xz`"

      # get pkg name only .. without versions or suffix
      PKGNAME_ONLY="`echo "${PKGNAME}" | sed -e 's/-[0-9.]*/-/g' -e 's/-$//'`"
      # if that didnt work, use the old method
      if [ "$PKGNAME_ONLY" = '' -o "$PKGNAME_ONLY" = "$PKGNAME" ];then
        # get pkg name without version 
        PKGNAMEONLY="`echo $PKGNAME | cut -d'-' -f1`" 
      fi
      PKGNAME_ONLY="${PKGNAME_ONLY//-*/}"
      
      # get pkg version
      PKGVER="`LANG=C echo "$LINE" | sed -e 's/^[^0-9]*-//g' | cut -f1 -d'_' | cut -f1 -d'-'`"
      # get pkg size
      SIZE="`echo $LINE| cut -d'"' -f6 | cut -d' ' -f3`"
      SIZE=${SIZE## }
      SIZE=${SIZE%% }
      # must check again if pkg had no deps
      [ "$SIZE" = "" ] && SIZE=" `echo $LINE| cut -d'"' -f6|cut -d' ' -f2`" 
      # get pkg category
      CAT="`echo $LINE | cut -d'"' -f6 | cut -d' ' -f1`"
      # remove extra categories
      [ "`echo "$CAT" | grep ';'`" != "" ] && CAT="`echo "$CAT" | cut -f1 -d';'`"
      # get pkg deps
      DEPS="`echo "$LINE" | cut -d'"' -f6 | cut -d' ' -f2 | grep ^'+'`" 
      DESC="`echo "$LINE" | cut -f10 -d'|'`"
      # build the woof compatible repo file
      [ "$PKGNAME" != "" ] && echo "$PKGNAME|$PKGNAMEONLY|$VER|$BUILD|$CAT|$SIZE|$SUBDIR|${PKGNAME}${PKGEXT}|$DEPS|$DESC|$DISTRO_BINARY_COMPAT|$DISTRO_COMPAT_VERSION||" >> $TMPDIR/$FILENAME
    done
    #done making a woof repo file, print message
    [ -f $TMPDIR/$FILENAME ] && echo "Finished converting $FILENAME to woof format." || exit 1
  fi

  # if we are updating the repo, we dont wanna install the converted file straight over 
  # the actual repo file, we wanna parse it for new pkgs and add only those
  if [ "$2" != "for_repo_update" ];then
    # we converted a repo that we actually wanna install, so install it
    mv $TMPDIR/$FILENAME ${HOME}/.packages/$FILENAME
    mv $TMPDIR/${FILENAME}_subdirs ${HOME}/.packages/${FILENAME}_subdirs 2>/dev/null
    echo "Repo file '${HOME}/.packages/$FILENAME' created." 
    update_sources #210613 update the list of sources after adding the newly converted repo
    #exit 0
  else 
    mv $TMPDIR/$FILENAME ${HOME}/$FILENAME
  fi
}


print_repo_info(){                # get repo settings, return current repo name FUNCLIST
  
  # get latest repo info (from sources file), or from PKGRC if that fails
  [ "$1" ] && get_repo_info $1 || . ${PKGRC}
  
  local pkg_count=`cat ${HOME}/.packages/${REPOFILE} | wc -l`
  
  # output the repo info
  echo "- Repo:          $REPONAME"
  echo "- Repo file:     $REPOFILE"
  echo "- Package Type:  $EX"
  echo "- Packages:      $pkg_count"
  echo "- URL Mirror 1:  `echo $REPOURL1 | cut -f1-3 -d'/'`"
  [ "$REPOURL2" != "" ] && echo "- URL Mirror 2:  `echo $REPOURL2  | cut -f1-3 -d'/'`"
  [ "$REPOURL3" != "" ] && echo "- URL Mirror 3:  `echo $REPOURL3  | cut -f1-3 -d'/'`"
  [ "$REPOURL4" != "" ] && echo "- URL Mirror 4:  `echo $REPOURL4  | cut -f1-3 -d'/'`"
  echo 
  echo "- Fall back to:`echo $REPOFALLBACKS | fold -w 50 -s | sed -e "s/ /, /g" -e "s/^/  /g"`"
}


#pkg funcs

hide_installed_pkgs_from_search_results(){  # hide BUILTIN and installed pkgs from searches NOLIST

  # dont hide package if using --force (the user may want to force a re-install of already installed pkg, for example)
  [ "$FORCE" = true ] && return 0
  
  # reset tmp file
  rm $TMPDIR/pkglist_inst &>/dev/null
  
  # get pkg names (generic names, no versions) of all installed pkgs (builtins, devx and user installed)
  inst_pkg_list="`cut -f1 -d'|' ${HOME}/.packages/user-installed-packages \
    ${HOME}/.packages/devx-only-installed-packages \
    ${HOME}/.packages/woof-installed-packages 2>/dev/null \
    | grep -v ^$ \
    | tr '\n' '|' \
    | sed -e "s/||/|/g" \
    | sed -e "s/|\$//g"`"
    
  # remove woof and user installed packages from search list
  cat $TMPDIR/pkglist | grep -v -E "'$inst_pkg_list'" > $TMPDIR/pkglist_without_inst
  mv $TMPDIR/pkglist_without_inst $TMPDIR/pkglist
  
  # clean up tmp files
  rm $TMPDIR/pkglist_* &>/dev/null
}


list_pkg_names(){                # list (matching) pkg names of current repo only FUNCLIST
  
  # remove any previous searches
  rm $TMPDIR/pkglist* 2>/dev/null

  # get current repo ($REPOFILE)
  . ${PKGRC}
  
  # create the search results
  cut -f1 -d'|' ${HOME}/.packages/${REPOFILE} 2>/dev/null | grep "^$1" > $TMPDIR/pkglist

  # filter out builtin and user installed packages
  if [ $HIDE_INSTALLED = true ];then
    hide_installed_pkgs_from_search_results
  fi

  # support pkg name aliases in finding packages
  if [ $NO_ALIASES = false ];then
    local ALIAS_LIST
    local ALIAS
    local ALIAS_RES
    # if we have some results to parse
    if [ "$1" != "" -a -f $TMPDIR/pkg_aliases ];then
      # get the list of aliases
      ALIAS_LIST="`grep -m1 "$1" $TMPDIR/pkg_aliases  2>/dev/null | tr ',' ' '`";
      # for each alias
      echo $ALIAS_LIST | while read ALIAS
      do 
        [ "$ALIAS" = '' ] && continue
        # get the match from the current repo (if any)
        ALIAS_RES="`LANG=C cut -f1 -d'|' ${HOME}/.packages/${REPOFILE} 2>/dev/null | grep "^$ALIAS"`" #'
        [ ! "$ALIAS_RES" ] && ALIAS_RES="`LANG=C cut -f2 -d'|' ${HOME}/.packages/${REPOFILE} 2>/dev/null | grep "^$ALIAS"`" #'
        # if the repo match was found in the search results
        if [ "$ALIAS_RES" != "" ];then
          # add the alias results to the search results
          echo "$ALIAS_RES" >> $TMPDIR/pkglist
        fi
      done # for each alias
      # sort and clean the search results
      LANG=C cat $TMPDIR/pkglist | sort --field-separator='-' -k1,1df -k2gr -k3gr -k4gr | uniq > $TMPDIR/pkglist1
      # replace the original search results
      mv $TMPDIR/pkglist1 $TMPDIR/pkglist
    fi
  fi
  
  # return the search results
  [ -s $TMPDIR/pkglist ] && cat $TMPDIR/pkglist 2>/dev/null

  # clean up
  [ ! -f $TMPDIR/pkglist ] && exit 1
  rm $TMPDIR/pkglist* 2>/dev/null

}


list_all_pkg_names(){            # list (matching) pkg names of any repo FUNCLIST
  
  # remove any previous search results
  rm $TMPDIR/pkglist &>/dev/null
  
  # if bleeding edge disabled, output the list repo by repo, in the fallback order, current repo first (that order is set in update_sources) 
  LANG=C list_sources_files | while read repo_file
  do
    LANG=C cut -f1 -d'|' ${HOME}/.packages/${repo_file} 2>/dev/null | grep "^$1" | sort --field-separator='-' -k1,1df -k2gr -k3gr -k4gr >> $TMPDIR/pkglist
  done

  # if bleeding edge enabled, re-order the whole list, so Pkg returns the most recent pgk versions from ANY repos
  if [ "$BLEDGE" = "yes" ];then 
    LANG=C cat $TMPDIR/pkglist  2>/dev/null | sort --field-separator='-' -k1,1df -k2gr -k3gr -k4gr > $TMPDIR/pkglist1
    mv $TMPDIR/pkglist1 $TMPDIR/pkglist
  fi
  
  # filter out built-in and user installed packages
  if [ $HIDE_INSTALLED = true ];then
    hide_installed_pkgs_from_search_results
  fi

  # support pkg name aliases in finding packages
  if [ $NO_ALIASES = false ];then
    local ALIAS_LIST
    local ALIAS
    local ALIAS_RES
    # if we have some results to parse 
    if [ "$1" != "" -a -f $TMPDIR/pkg_aliases ];then
      # get the list of aliases
      ALIAS_LIST="`grep -m1 "$1" $TMPDIR/pkg_aliases  2>/dev/null | tr ',' ' '`";
      # for each repo
      LANG=C list_sources_files | while read RF
      do
        # and for each alias
        for ALIAS in $ALIAS_LIST; do
          # get the match from the current repo (if any) 
          ALIAS_RES="`LANG=C cut -f1 -d'|' ${HOME}/.packages/${RF} 2>/dev/null | grep -m1 "^$ALIAS"`"
          [ ! "$ALIAS_RES" ] && ALIAS_RES="`LANG=C cut -f2 -d'|' ${HOME}/.packages/${RF} 2>/dev/null | grep -m1 "^$ALIAS"`"
          # if the repo match was found in the search results 
          if [ "$ALIAS_RES" != "" ];then
            # add the alias results to the search results
            echo "$ALIAS_RES" >> $TMPDIR/pkglist
          fi
        done # for each alias
      done # for each repo
    fi
  fi

  # return the search results
  [ -s $TMPDIR/pkglist ] && LANG=C cat $TMPDIR/pkglist | sort --field-separator='-' -k1,1df -k2gr -k3gr -k4gr | uniq

  # clean up
  [ ! -f $TMPDIR/pkglist ] && exit 1
  rm $TMPDIR/pkglist &>/dev/null
}


which_repo(){                    # list matching pkg and its repo, in any repo FUNCLIST

  # if no valid options, quit
  [ ! "$1" -o "$1" = "-" -o "$1" = " " ] && print_usage which-repo && exit 1

  . ${PKGRC}
  
  local PKGNAME=''
  local PKGNAME_ONLY=''
  local pkg_ext=''
  local repo_file=''
  local repo_name=''
  local pkg_list=''
  
  PKGNAME=`get_pkg_name "$1"`
  PKGNAME_ONLY=`get_pkg_name_only "$1"`
  pkg_ext=`get_pkg_ext "$PKGNAME"`

  repo_file="`grep -l "|$PKGNAME.$pkg_ext|" ${HOME}/.packages/Packages-*`"
  if [ "$repo_file" != '' ];then
    # get the repo name
    repo_name="`grep -m1 "$(basename $repo_file)|" ${HOME}/.pkg/sources | cut -f1 -d'|'`"
    pkg_list="$PKGNAME $repo_name"
  else

    # for each repo
    for repo_file in `list_sources_files`
    do
      # get the repo name
      repo_name="`grep -m1 "$repo_file|" ${HOME}/.pkg/sources | cut -f1 -d'|'`"
      # create a the entries, example: "vlc slacko14.2"
      # (each line shows a matching package, then a SPACE, then the name of repo the package lives in)
      pkg_list="$pkg_list`LANG=C grep "$PKGNAME" ${HOME}/.packages/${repo_file} 2>/dev/null | grep -m1 "^$PKGNAME|" | cut -f1 -d'|' | tr '\n' '@' | sed -e "s#@# $repo_name\n#g"`"
      [ "$pkg_list" = '' ] && pkg_list="$pkg_list`LANG=C grep "$PKGNAME" ${HOME}/.packages/${repo_file} 2>/dev/null | grep -m1 "|$PKGNAME_ONLY|" | cut -f1 -d'|' | tr '\n' '@' | sed -e "s#@# $repo_name\n#g"`"
      [ "$pkg_list" = '' ] && pkg_list="$pkg_list`LANG=C grep "$PKGNAME" ${HOME}/.packages/${repo_file} 2>/dev/null | grep -m1 "^$PKGNAME_ONLY|" | cut -f1 -d'|' | tr '\n' '@' | sed -e "s#@# $repo_name\n#g"`"
      [ "$pkg_list" = '' ] && pkg_list="$pkg_list`LANG=C grep "$PKGNAME" ${HOME}/.packages/${repo_file} 2>/dev/null | grep -m1 "|$PKGNAME.$EX|" | cut -f1 -d'|' | tr '\n' '@' | sed -e "s#@# $repo_name\n#g"`"
      [ "$pkg_list" = '' ] && pkg_list="$pkg_list`LANG=C grep "$PKGNAME" ${HOME}/.packages/${repo_file} 2>/dev/null | grep -m1 "|$1.$EX|" | cut -f1 -d'|' | tr '\n' '@' | sed -e "s#@# $repo_name\n#g"`"
      [ "$pkg_list" = '' ] && pkg_list="$pkg_list`LANG=C grep "$PKGNAME" ${HOME}/.packages/${repo_file} 2>/dev/null | grep -m1 "|$1|" | cut -f1 -d'|' | tr '\n' '@' | sed -e "s#@# $repo_name\n#g"`"
      [ "$pkg_list" = '' ] && pkg_list="$pkg_list`LANG=C grep "$PKGNAME" ${HOME}/.packages/${repo_file} 2>/dev/null | grep -m1 "^$1|" | cut -f1 -d'|' | tr '\n' '@' | sed -e "s#@# $repo_name\n#g"`"
    done
  fi

  # show results
  LANG=C echo -e "$pkg_list" | sed -e '/^$/d' | uniq
}


search_pkgs(){                   # current repo, show pkg name and desc in columns FUNCLIST
  
  local name
  local desc
  local descfull
  
  # convert repo file to nice columnised output, use cat|grep so empty searches return all results
  cat ${HOME}/.packages/${REPOFILE} 2>/dev/null | grep -i "$1" | while read repo_line; 
  do 
    name=`echo  "$repo_line"|cut -f2  -d'|'`
    desc="`echo "$repo_line"|cut -f10 -d'|' | head -c 57`"
    descfull="`echo "$repo_line"|cut -f10 -d'|'`"
    [ "$desc" != "$descfull" ] && desc="${desc}.."
    printf "%-20s" "$name" " ${desc:-No description}"
    echo
  done
}


search_fast(){                   # current repo, show pkg names only, case sensitive FUNCLIST
  local RES
  # get matching pkgs
  RES="`LANG=C grep "$1" ${HOME}/.packages/${REPOFILE} 2>/dev/null | cut -f1 -d'|'`" #'
  # error if no result
  [ ! "$RES" ] && exit 1

  # put results into file 
  echo "$RES" > $TMPDIR/pkglist

  # hide built-in, devx and user installed packages
  if [ $HIDE_INSTALLED = true ];then
    hide_installed_pkgs_from_search_results
  fi

  # now build the search results
  RES="`grep -v "^\$" $TMPDIR/pkglist 2>/dev/null | sort --field-separator='-' -k1,1df -k2gr -k3gr -k4gr | uniq`"
  rm $TMPDIR/pkglist &>/dev/null

  #finshed making search results, print results
  [ "$RES" = "" ] && exit 1
  echo "$RES"
}


search_all_pkgs(){               # all repos, show pkg name and desc in columns FUNCLIST
  
  local name
  local desc
  local descfull


  for repo_file in `list_sources_files`
  do #090817
    # convert repo file to nice columnised output
    cat ${HOME}/.packages/${repo_file} 2>/dev/null | grep -i "$1" | while read repo_line;
    do
    # get details from repo
    name=`echo  "$repo_line"|cut -f2  -d'|'`
    desc="`echo "$repo_line"|cut -f10 -d'|' | head -c 57`"
    descfull="`echo "$repo_line"|cut -f10 -d'|'`"
    [ "$desc" != "$descfull" ] && desc="${desc}.."
    # remove spaces and comments (slackware-extra repo has some dodgy entries.. dogy names, descriptions with comments, etc)
    name="${name// /}"
    name="${name//#/}"
    [ "$name" = '' ] && continue
    # print columnised output
    printf "%-20s" "$name" " ${desc:-No description}"
    echo
    done
  done

}


search_all_fast(){               # all repos, show pkg names only, case sensitive FUNCLIST
  
  local RES
  #if bleeding edge enabled, combine into 1 list, so 
  # that `pkg -g` etc return most recent from ALL repos
  rm $TMPDIR/pkglist &>/dev/null
  if [ "$BLEDGE" = "yes" ];then 
    RES=''
    for RF in `list_sources_files`
    do #090817
      cat ${HOME}/.packages/${RF} 2>/dev/null | grep -i "$1" | cut -f1 -d'|' | sort --field-separator='-' -k1,1df -k2gr -k3gr -k4gr | uniq | sed -e '/^$/d' >> $TMPDIR/pkglist
    done

  else 
    # if bleeding edge disabled, output the list repo by repo, in #
    # the fallback order, current repo first (that order is set in update_sources)
    for RF in `list_sources_files`
    do #090817
      cat ${HOME}/.packages/${RF} 2>/dev/null | grep -i "$1"| cut -f1 -d'|' | sort --field-separator='-' -k1,1df -k2gr -k3gr -k4gr | uniq | sed -e '/^$/d' >> $TMPDIR/pkglist
    done

  fi
  
  #100817 hide built-in, devx and user installed packages
  if [ $HIDE_INSTALLED = true ];then
    hide_installed_pkgs_from_search_results
  fi
  
  # now build the search results
  RES="`grep -v "^\$" $TMPDIR/pkglist 2>/dev/null | sort --field-separator='-' -k1,1df -k2gr -k3gr -k4gr | uniq`"
  rm $TMPDIR/pkglist &>/dev/null

  #finshed making search results, print results
  [ "$RES" = "" ] && exit 1

  echo "$RES"
}


pkg_contents(){                  # list package contents FUNCLIST
  
  # if no valid options, quit
  [ ! "$1" -o "$1" = "-" -o "$1" = " " ] && print_usage contents && exit 1

  # get settings
  . ${PKGRC}
  
  local PKGFILE
  local ext
  local PKGNAME
  local PKGNAME_ONLY
  local pkg_is_local_file
  local pkg_is_builtin
  local pkg_is_installed
  local PKGFLIST=''
  
  # get pkg extension
  ext=`get_pkg_ext "$1"`
  
  # get pkg name (includes version), but no extension or path
  PKGNAME="$(basename "$1" .$ext)"
  PKGNAME=`get_pkg_name "$PKGNAME"`

  # get pkg name without version
  PKGNAME_ONLY=`get_pkg_name_only "$PKGNAME"`
  
  pkg_is_local_file=`is_local_pkg "$1"`
  pkg_is_builtin=`is_builtin_pkg "$PKGNAME_ONLY"`
  pkg_is_installed=`is_installed_pkg "$PKGNAME_ONLY"`

  # now we check various ways to find out the contents of 
  # a pkg (either by *.files, user installed, woof, builtin, etc)
  
  [ "$pkg_is_local_file" = true ] && PKGFILE="$1"

  # try a file in the current dir if needed
  [ ! -f "$PKGFILE" ] && PKGFILE="${CURDIR}/${PKGNAME}.$ext"
  # check $WORKDIR if needed
  [ ! -f "$PKGFILE" ] && PKGFILE="${WORKDIR}/${PKGNAME}.$ext"
  
  # if the pkg is a local file
  if [ -f "$PKGFILE" ];then
    #list contents based on extension
    case "$ext" in 
    sfs)
      unsquashfs -l "$PKGFILE"  | cut -f2-99 -d'/'| sed -e 's#^#/#g' | grep -v -E 'unsquashfs:|/squashfs-root|) to write'
    ;;
    deb)
      dpkg-deb -c "$PKGFILE" 2>/dev/null
     ;;
    pet|tar|*tcz|*txz|*tgz|*xz|*gz) 
      # remove leading pkg name from each line of file list 
      # (shown if listing *some* pkg file contents)
      tar -tf "$PKGFILE" 2>/dev/null \
        | sed -e "s#^./${PKGNAME}##g" -e "s#^${PKGNAME}##g" -e "s#^./##g" \
        | grep -v ^$ 
    ;;
    rpm)
      busybox rpm -qlp "$PKGFILE" 2>/dev/null
    ;;
    esac
    exit $?
  fi

  # if we are here, the pkg is not a downloaded pkg, so we build a 
  # list of files by checking  *.files, woof, builtins .. 
  
  # check if we need to (and can) get our pkg contents from builtins/PKGNAME
  local  need_to_check_builtins=`echo "$PKG_FLIST" | grep -m1 'packages/builtin_files/'`
  
  # if the pkg is a builtin, we will re-format the output of LIST to match the others (full paths on each line)
  if [ "$need_to_check_builtins" != '' -a "$pkg_is_builtin" = true ];then
  
    # reset the list of pkg files, we will re-build it
    rm $TMPDIR/pkg_file_list 2>/dev/null

    # first we get the package contents from $HOME/.packages/builtin_files/$PKGNAME_ONLY 
    cat "$PKG_FLIST" 2>/dev/null | while read line
    do 
      # parse it, so we get a full path to file on each line
      if [ "`echo "$line" | grep '^/'`" != '' ];then
        # set the dir to use in our file list 
        dir="$line"
      else
        # keep previous dir
        dir="$dir"
      fi

      # create our new line (a full file path) to $LIST
      line_to_add="$dir/`echo "$line" | cut -f2 -d' '`"
      
      # if only a dir, skip it
      [ "$line" = "$dir" ] && continue

      # if its already added, skip it
      [ "`grep -m1 "$line_to_add" ${TMPDIR}/pkg_file_list 2>/dev/null `" != '' ] && continue
      
      # if its not a file on the system (it should be), skip it
      [ ! -f "$line_to_add" ] && continue
      
      # all should be ok, add the line to our list
      echo "$line_to_add" >> $TMPDIR/pkg_file_list

    done

    # now get our pkg contents list, it might have been re-formatted (if a builtin)
    PKG_FLIST="`cat ${TMPDIR}pkg_file_list 2>/dev/null`"
    
    # last resort, if we lost our file list or still dont have, try the basics again
    [ "$PKG_FLIST" = '' ] && PKG_FLIST="`find $HOME/.packages/ -maxdepth 1 -type f -name "${PKGNAME}*.files" 2>/dev/null`"

    # clean up the list a bit
    [ "$PKG_FLIST" != '' ] && PKG_FLIST="`echo "$PKG_FLIST" | grep -v ' ' | grep -v "^\$" | sort | uniq`"
    
    # and clean up the tmp files
    rm ${TMPDIR}pkg_file_list 2>/dev/null
  fi
  
  # try finding PKGNAME.files
  PKG_FLIST="`find $HOME/.packages/ -maxdepth 1 -type f -name "${PKGNAME}.files" 2>/dev/null`"
  
  # try the builtins files (exact match)
  [ "$PKG_FLIST" = "" ] && PKG_FLIST="`find $HOME/.packages/builtin_files/ -maxdepth 1 -type f -name "$PKGNAME_ONLY"`" 
  
  # try PKGNAME (exact match) in user installed pkgs
  [ "$PKG_FLIST" = "" ] && PKG_FLIST="`cut -f1 -d'|' $HOME/.packages/user-installed-packages | grep -m1 ^"$PKGNAME\$" 2>/dev/null`"
  
  # try PKGNAME (exact match) in all installed pkgs
  [ "$PKG_FLIST" = "" ] && PKG_FLIST="`cut -f1 -d'|' $HOME/.packages/*-installed-packages | grep -m1 ^"$PKGNAME\$" 2>/dev/null`"
  
  # try PKGNAME_ONLY (exact match) in user installed pkgs
  [ "$PKG_FLIST" = "" ] && PKG_FLIST="`cut -f2 -d'|' $HOME/.packages/user-installed-packages | grep -m1 ^"$PKGNAME_ONLY\$" 2>/dev/null`"
  
  # try PKGNAME_ONLY (exact match) in all installed pkgs
  [ "$PKG_FLIST" = "" ] && PKG_FLIST="`cut -f2 -d'|' $HOME/.packages/*-installed-packages | grep -m1 ^"$PKGNAME_ONLY\$" 2>/dev/null`"
  
  # try finding *PKGNAME.files
  [ "$PKG_FLIST" = "" ] && PKG_FLIST="`find $HOME/.packages/ -maxdepth 1 -type f -name "*${PKGNAME}.files" 2>/dev/null`"
  
  # try PKGNAME*.files
  [ "$PKG_FLIST" = "" ] && PKG_FLIST="`find $HOME/.packages/ -maxdepth 1 -type f -name "/${PKGNAME}*.files"  2>/dev/null`"
  
  # try $HOME/.packages/*-installed-packages, fuzzy search
  
  # try PKGNAME_ONLY-* in user installed pkgs only
  [ "$PKG_FLIST" = "" ] && PKG_FLIST="`cut -f1 -d'|' $HOME/.packages/user-installed-packages | grep -m1 ^"${PKGNAME_ONLY}-" 2>/dev/null`"
  
  # try PKGNAME_ONLY_* in user installed pkgs only
  [ "$PKG_FLIST" = "" ] && PKG_FLIST="`cut -f1 -d'|' $HOME/.packages/user-installed-packages | grep -m1 ^"${PKGNAME_ONLY}_" 2>/dev/null`"
  
  # try PKGNAME_ONLY* in user installed pkgs only
  [ "$PKG_FLIST" = "" ] && PKG_FLIST="`cut -f1 -d'|' $HOME/.packages/user-installed-packages | grep -m1 ^"$PKGNAME_ONLY" 2>/dev/null`"
  
  # try PKGNAME_ONLY-* (any installed pkgs)
  [ "$PKG_FLIST" = "" ] && PKG_FLIST="`cut -f1 -d'|' $HOME/.packages/*-installed-packages | grep -m1 ^"${PKGNAME_ONLY}-" 2>/dev/null`"
  
  # try PKGNAME_ONLY_* (any installed pkgs)
  [ "$PKG_FLIST" = "" ] && PKG_FLIST="`cut -f1 -d'|' $HOME/.packages/*-installed-packages | grep -m1 ^"${PKGNAME_ONLY}_" 2>/dev/null`"
  
  # try PKGNAME_ONLY* (any installed pkgs)
  [ "$PKG_FLIST" = "" ] && PKG_FLIST="`cut -f1 -d'|' $HOME/.packages/*-installed-packages | grep -m1 ^"$PKGNAME_ONLY" 2>/dev/null`"
  
  # try PKGNAME_ONLY*.files
  [ "$PKG_FLIST" = "" ] && PKG_FLIST="`find $HOME/.packages/ -maxdepth 1 -type f -name "/${PKGNAME_ONLY}*.files"  2>/dev/null`"


  
  #if we found a list of files
  if [ "$PKG_FLIST" != "" ];then
    
    print_cmd=echo
    # PKG_FLIST just might contain a path to the pkg contents 
    # themselves (a *.files, or a file in builtin_files/*).. so if 
    # its a file path, we will cat it, if not, its the pkg contents 
    # themselves, we echo it
    if [ "`echo "$PKG_FLIST" | grep -m1 '/builtin_files/'`" != '' -o "`echo "$PKG_FLIST" | grep -m1 "packages/$PKGNAME"`" != '' ];then
      print_cmd=cat
    fi

    $print_cmd "$PKG_FLIST" 2>/dev/null
    
  else # if no files found
    if [ "$PKGNAME" != '' ];then
      INST_CHECK="`is_installed_pkg $PKGNAME 2>/dev/null`"
      if [ "$INST_CHECK" != true -o "$pkg_is_local_file" = false ];then
        error "Package must be installed, downloaded or built-in."
      else
        error "Could not get package contents, unable to get file list."
      fi
    else
      error "Could not get name of package."
    fi
  fi
}


prepare_petbuild(){              # get 01mickos petbuild system from Git, if needed FUNCLIST

  local gitcheck=`which git`
  
  # exit if no devx
  [ "`which gcc`" = '' ] && echo "You need the devx SFS installed to compile packages." && rm /tmp/pkg/petbuild_prepared 2>/dev/null && exit 3
  # exit if no git
  [ "`$gitcheck`" = '' ] && echo "You need git installed to auto-install petbuild." && rm /tmp/pkg/petbuild_prepared 2>/dev/null && exit 3

  if [ ! -d /usr/share/petbuild ];then
    rm /tmp/pkg/petbuild_prepared 2>/dev/null && exit 1
  fi
  
  # if buildpet prepared flag not yet set
  if [ ! -f /tmp/pkg/petbuild_prepared ];then
  
    # backup old petbuild if installed
    [ -d /usr/share/petbuild/ ] && mv /usr/share/petbuild/ /usr/share/petbuild.backup/ 2>/dev/null
    
    # inform user if we backed up their old PetBuild
    [ -d /usr/share/petbuild.backup/ ] && echo "Previous PetBuild install backed up to /usr/share/petbuild.backup/"

    # clone petbuild into /usr/share/petbuild
    git clone https://github.com/puppylinux-woof-CE/petbuilds.git /usr/share/petbuild #|| return 128
    
    # exit if git failed
    if [ $? -eq 128 ];then
      rm /tmp/pkg/petbuild_prepared 2>/dev/null
      echo "Could not clone PetBuild repo"
      exit 1
    fi
    
    # if still no petbuild dir in /usr/share, tell user to install themselves
    if [ ! -d /usr/share/petbuild ];then
      echo 
      echo "Run this command to download PetBuild:"
      echo 
      echo -e " ${green}git clone https://github.com/puppylinux-woof-CE/petbuilds /usr/share/petbuild${endcolour}"
      echo
      echo "Alternatively, use a different build tool backend by changing BUILDTOOL= "
      echo "to one of the options below, in your $PKGRC file:"
      echo "petbuild, buildpet, sbopkg or src2pkg"
      echo ""

      exit 1
    fi
    
    # go into buildpet dir, check which Pup we have ($DISTRO_DB_SUBNAME) 
    # and checkout the right branch for the running system
    cd /usr/share/petbuild 
    
    # check the puppy running and checkout the relevant branch
    if [ "`echo $DISTRO_DB_SUBNAME | grep slacko`" != '' ];then
      if [ "`echo $DISTRO_DB_SUBNAME | grep '14.2'`" != '' ];then
        git checkout slacko_142
      else 
        git checkout slacko_141
      fi
    elif [ "`echo $DISTRO_DB_SUBNAME | grep tahrpup`" ];then
      git checkout tahrpup
    elif [ "`echo $DISTRO_DB_SUBNAME | grep stretch`" ];then
      git checkout stretch || git checkout tahrpup
    elif [ "`echo $DISTRO_DB_SUBNAME | grep xenialpup`" ];then
      git checkout xenialpup || git checkout tahrpup
    elif [ "$DISTRO_DB_SUBNAME" != '' ];then
      git checkout tahrpup
    else 
      echo "No pet builds available for your system ($DISTRO_DB_SUBNAME),"
      echo "using buildpet instead.."
      rm -rf /usr/share/petbuild 2>/dev/null
    fi
    
    # buildpet setup finished, create flag
    echo 'true' > /tmp/pkg/petbuild_prepared
  
    cd "$CURDIR"
  fi
}


pkg_build(){                     # builds packages from source (see BUILDTOOL in pkgrc) FUNCLIST
  
  # exit if devx not installed
  [ "`which gcc`" = "" ]   && echo "You need the devx SFS installed to compile." && exit 1
  
  # get the settins from RC file
  . ${PKGRC}
  
  # we do a different build method for each supported build tool
  case $BUILDTOOL in 
    
    petbuild) # by 01micko

      # use git to install the latest petbuild
      prepare_petbuild

      # if petbuild not installed, quit
      [ ! -d /usr/share/petbuild ] && error "PetBuild not installed at /usr/share/petbuild." && exit 3

      # petbuild needs a package name, or exit
      [ ! "$1" -o "$1" = "-" ] && print_usage pkg-build && exit 1 #220613 #250613
      
      # get pkg extension
      EX=`get_pkg_ext "$1"`
      
      #get pkg name only, no extension or path
      PKGNAME="$(basename "$1" .$EX)"

      # get petbuild PKGNAME, then build using 01mickos petbuild
      BUILDSCRIPT="`find /usr/share/petbuild -iname ${PKGNAME}"*.petbuild"| grep -m1 "$PKGNAME"`"
      
      # if we got a build script
      if [ -f "$BUILDSCRIPT" ];then
        cd `dirname "$BUILDSCRIPT"`
        # compile the pkg
        bash *.petbuild
        # after build, move any pets created to WORKDIR
        mv /usr/share/petbuild/0pets_out/*.pet "$WORKDIR" 2>/dev/null
        # back to prev dir (WORKDIR)
        cd -
      fi
      
      # if build script not found, exit
      [ ! -f "$BUILDSCRIPT" ] && echo "Build script for '$PKGNAME' not found in /usr/share/petbuild/" && exit 1

      # get the packages we just moved to WORKDIR
      PKGFILES="`find "$WORKDIR" -iname "$PKGNAME*.pet"`"
      
      # list any packages we just built
      [ "$PKGFILES" != '' ] && echo -e "${green}Success:${endcolour} Packages in $WORKDIR:" && echo "$PKGFILES"
    ;;
  
    buildpet) # by Tman/iguleder

      # exit if buildpet dir not found
      [ ! -d /usr/share/buildpet ] && error "buildpet not installed." && exit 1

      # buildpet expects a PKGNAME, or exit
      [ ! "$1" -o "$1" = "-" ] && print_usage pkg-build && exit 1
      
      # get pkg extension
      EX=`get_pkg_ext "$1"`
      
      # get pkg name (with version), no extension or path
      PKGNAME="$(basename "$1" .$EX)"

      # get the buildpet script of PKGNAME
      BUILDSCRIPT="`find /usr/share/buildpet/ -name $PKGNAME"*"`"
      
      # if build script not found, exit
      [ ! -f "$BUILDSCRIPT" ] && echo "Build script for '$PKGNAME' not found in /usr/share/buildpet/" && exit 1

      # now compile the package
      buildpet $BUILDSCRIPT

    ;;
  
    src2pkg)  # by amigo

      ### This code is a horribly simple wrapper to a great tool..
      ### Implement all src2pkg options here at some point..
      ##
      ### We should pass all options to src2pkg, and make it build a 
      ### (petbuild|buildpet) buildscipt on successful compile
      
      # exit if src2pkg not installed
      [ "`which src2pkg`" = '' ] && error "src2pkg not installed." && error "Get it from http://distro.ibiblio.org/amigolinux/download/src2pkg/src2pkg-3.0-noarch-2.txz" && exit 3
      
      # exit if $1 not given or valid
      [ ! "$1" -o "$1" = "-" ]   && print_usage pkg-build && exit 1 
      
      # show src2pkg help if user supplied any of the help options 
      if [ "$1" = '-h'  -o "$1" = '-hh'  -o "$1" = '--help' -o "$1" = '--more-help' -o "$1" = '--list' ];then
        src2pkg $1 | sed -e "s/  src2pkg /  $SELF -pb /g"
        echo -e "\n   See 'src2pkg' by amigo"
        exit 0
      fi
      
      # get pkg extension.. not really needed here
      EX=`get_pkg_ext "$1"`
      
      # use amigos src2pkg
      src2pkg $1
      
      # if src2pkg exited without error, copy any pets it made to WORKDIR
      [ $? -eq 0 ] && mv /tmp/*.pet "$WORKDIR" 2>/dev/null

    ;;
  
    sbopkg)   # slackware peeps
      
      # exit if not installed
      [ "`which sbopkg`" = '' ] && error "Sbopkg not installed." && exit 3

      # exit if no valid options
      [ ! "$1" -o "$1" = "-" ]  && print_usage pkg-build && exit 1
      
      sbopkg -b "$1"
      
      # move any built pkgs to WORKDIR.. need a better way to do this
      if [ "`find /tmp/* -iname $1*.t*`" != '' ];then
        mv /tmp/*.tgz "$WORKDIR" 2>/dev/null
        mv /tmp/*.txz "$WORKDIR" 2>/dev/null
        mv /tmp/*.tar.xz "$WORKDIR" 2>/dev/null
        echo -e "DONE... The package should be in $WORKDIR."
      fi

    ;;
  
  *)
    # get pkg name only, no extension or path
    PKGNAME="$(basename "$1" .$EX)"

    echo "Cannot compile '$PKGNAME', no build system installed."
    echo
    echo "Please install one of the following:"
    echo " * petbuild by 01micko: http://murga-linux.com/puppy/viewtopic.php?t=96027"
    echo " * buildpet by Tman:    http://murga-linux.com/puppy/viewtopic.php?t=81056"
    echo " * src2pkg  by amigo:   http://distro.ibiblio.org/amigolinux/download/src2pkg/"
    echo " * sbopkg   by various: https://www.sbopkg.org/downloads.php"
    echo
    echo "Then set BUILDTOOL to either petbuild, buildpet, src2pkg or sbopkg "
    echo "in $PKGRC to enable building packages from source."
    echo
    echo "NOTE:"
    echo "01mickos petbuild should be installed to /usr/share/petbuild"
    echo "And Tmans buildpet should be installed to /usr/share/buildpet"
  ;;
  esac
}


list_build_scripts(){            # list available build scripts FUNCLIST
  
  # get settings from RC file
  . ${PKGRC}
  
  # make sure PetBuild is ready
  prepare_petbuild
  
  # if no option given, just sort the results
  [ "$1" != "" ] && FILTER="grep -i $1" || FILTER="sort"
  
  # different build tools have their build scripts in different places.
  # check which BUILDTOOL we are using and list its build scripts
  case $BUILDTOOL in
    petbuild)
      echo "$(LANG=C ls -R -1 /usr/share/petbuild/ 2>/dev/null | grep -v ^'/' | grep -v ^$ | grep '.petbuild' | sed -e "s/.petbuild$//g" | sort | $FILTER)" | grep -v ^$
    ;;
    buildpet)
      echo "$(LANG=C ls -R -1 /usr/share/buildpet/ 2>/dev/null  | grep -v ^'/' | grep -v ^$ | grep -v 'buildpet.profile' | sed -e "s/.bp$//g" | sort | $FILTER)" | grep -v ^$
    ;;
    src2pkg)
      echo "Use: src2pkg FILE|URL or src2pkg -h"
    ;;
    sbopkg)
      sbopkg
    ;;
    *)
      echo "No build system configured. Set BUILDTOOL in $PKGRC."
      echo "Supported build tools: petbuild, buildpet, src2pkg, sbopkg"
    ;;
  esac
}


pkg_repack(){                    # create package from its *.files list FUNCLIST
  
  # exit if no valid options
  [ ! "$1" -o "$1" = "-" ] && print_usage pkg-repack && exit 1
  
  local list=''
  local pkg_ext=''
  local PKGNAME=''
  local PKGNAME_ONLY=''
  local dir=''
  local build_number=''
  
  # get pkg extension
  pkg_ext=`get_pkg_ext "$1"`
  
  #get pkg name only, no extension or path
  PKGNAME="$(LANG=C basename "$1" .$pkg_ext)" 
  
  # assume the file name from $1
  PKGFILE="${CURDIR}/${PKGNAME}.$pkg_ext" 
  
  # don't rely on the given pkg name string, get the full name from repo if poss
  PKGNAME=`get_pkg_name "$PKGNAME"`

  # get pkg name without version
  PKGNAME_ONLY="`get_pkg_name_only "${PKGNAME}"`"
  
  # if the list is empty, pkg is not user installed or built in, cant show contents
  [ "`is_installed_pkg "$PKGNAME"`" = false ] && echo "$PKGNAME needs to be installed." && exit 1

  # if the package to built already exists, ask user to delete it
  [ -f "${PKGFILE}" ] && echo "$PKGNAME.$pkg_ext already exists in $CURDIR" && rm -f "${PKGFILE}" 2>/dev/null

  # if pkg exists, user didn't delete it
  [ -f "${PKGFILE}" ] && exit 0
  
  # get the build number, and increment by one
  build_number="`grep -m1 "^$PKGNAME|$PKGNAME_ONLY|" ${HOME}/.packages/user-installed-packages ${HOME}/.packages/woof-installed-packages ${HOME}/.packages/devx-only-installed-packages ${HOME}/.packages/Packages-* | cut -f4 -d'|'`"
  build_number=${build_number:-0}
  build_number="-$(($build_number + 1))"
  
  # process the file list, copy each file to our pkg folder
  pkg_contents "$PKGNAME_ONLY" | while read line
  do
    if [ -f "$line" ]; then
      linedir="$(dirname "${line}")"
      [ ! -d "${CURDIR}/$PKGNAME/${linedir}" ] && mkdir -p "${CURDIR}/$PKGNAME/${linedir}"
      cp -p -P "$line" "${CURDIR}/${PKGNAME}/${linedir}"
    fi
  done
  
  sync
  
  # make sure we populated a pkg folder, ready to package up
  [ ! -d "${CURDIR}/${PKGNAME}/" ] && error "No '$PKGNAME' directory in $CURDIR" && exit 5

  # pkg folder should be populated, now package it up and print final msg
  dir2pet "${CURDIR}/${PKGNAME}/" "$build_number"
  rm -rf "${CURDIR}/${PKGNAME}/" 2>/dev/null
  rm -rf "${CURDIR}/${PKGNAME}$build_number/" 2>/dev/null
  sync 
}


pkg_unpack(){                    # extract (unpack) $1 to current dir
  
  # exit if not valid usage
  [ ! -f "$1" ] && print_usage unpack && exit 1
  
  local PKGNAME
  local PKGFILE
  local PKGEXT
  local comp
  
  # get pkg details
  PKGFILE="$1"
  PKGNAME=`get_pkg_name "$PKGFILE"`
  PKGEXT=`get_pkg_ext "$PKGFILE"`
  
  # exit if we dont have enough info
  [ "$PKGEXT" = '' ]  && error "Cant get package extension" && exit 1
  [ ! -f "$PKGFILE" ] && error "Cant find $1" && exit 6
  [ "$PKGNAME" = '' ] && error "Cant get PKGNAME" && exit 3
  
  # determine compression utility
  case $PKGEXT in
    
    deb)
      mkdir "$PKGNAME" 2>/dev/null
      rm -rf "$PKGNAME"/* 2>/dev/null
      dpkg-deb -x "$PKGFILE" "$PKGNAME"    # extracts main pkg contents
      result=$?
      dpkg-deb -e "$PKGFILE" "$PKGNAME"/DEBIAN # extracts deb control files
      [ $result -eq 0 ] && echo -e "${green}Success${endcolour}: File ${magenta}`basename $PKGFILE`${endcolour} extracted." || error "Cannot extract $PKGFILE"
      return $result
      ;;
      
    rpm)
      mkdir "${PKGNAME}" 2>/dev/null
      rm -rf "$PKGNAME"/* 2>/dev/null
      # create dir called $PKGNAME, cd into it, extract the rpm in there
      cp "$PKGFILE" "$PKGNAME/"
      cd "$PKGNAME" 1>/dev/null
      # now extract the rpm contents into current dir
      exploderpm -x "$PKGFILE" &>/dev/null
      result=$?
      # clean up and leave
      rm -f *.rpm 2>/dev/null
      cd - 1>/dev/null
      # final msg
      [ $result -eq 0 ] && echo -e "${green}Success${endcolour}: File ${magenta}`basename $PKGFILE`${endcolour} extracted." || error "Cannot extract $PKGFILE"
      return $result
      ;;
      
    sfs) 
    
      mkdir "/${PKGNAME}" 2>/dev/null
      rm -rf "$PKGNAME"/* 2>/dev/null
      
      # make mnt dir, mount sfs
      mkdir "/mnt/${PKGNAME}" 2>/dev/null
      mount -t squashfs "$PKGFILE" /mnt/"$PKGNAME" -o loop 1>/dev/null || { error "Could not mount $PKGFILE"; exit 3; }
      # copy sfs contents into ./$PKGNAME
      cp -a -Rf --remove-destination /mnt/"$PKGNAME" "$PKGNAME" || { error "Failed copying files from /mnt/$PKGNAME to ./$PKGNAME"; exit 4; }
      result=$?
      # clean up
      umount "/mnt/${PKGNAME}"
      rmdir "/mnt/${PKGNAME}"
      # final msg
      [ $result -eq 0 ] && echo -e "${green}Success${endcolour}: File ${magenta}`basename $PKGFILE`${endcolour} extracted." || { error "Cannot extract $PKGFILE"; exit 7; }
      return $result
      ;;
    pet)  file -b "$PKGFILE" | grep -i -q "^xz" && comp=xz || comp=gzip ;;
    tgz)  comp=gzip ;;
    gz)   comp=gzip ;;
    tbz)  comp=bzip2 ;;
    bz2)  comp=bzip2 ;;
    tlz)  comp=lzma ;;
    lzma) comp=lzma ;;
    txz)  comp=xz ;;
    xz)   comp=xz ;;
  esac
  sync

  # if pkg is extractable with tar, then unpack
  case $PKGEXT in
  pet|tgz|gz|tbz|bz2|tlz|lzma|txz|xz)
    ( umask 000 ; cat "$PKGFILE" | $comp -dc 2>/dev/null | tar -xf - 2> /dev/null && echo -e "${green}Success${endcolour}: File ${magenta}`basename $PKGFILE`${endcolour} extracted." || error "Cannot extract $PKGFILE" )
    ;;
  esac

  # return
  return ${result:-0}
  
}


pkg_entry(){                     # show pkg repo entry, each field on a new line FUNCLIST
  
  # exit if no valid opts
  [ ! "$1" -o "$1" = '-' ] && print_usage pkg-entry && exit 1

  local EX
  local PKGNAME
  local PKGNAME_ONLY
  
  # get pkg extension
  EX=`get_pkg_ext "$1"`

  # get pkg name with version, but no extension or path
  PKGNAME="$(basename "$1" .$EX)"
  
  # dont rely on the string the user gave us, try to get the exact match 
  PKGNAME=`get_pkg_name "$PKGNAME"`
  PKGNAME_ONLY=`get_pkg_name_only "$PKGNAME"`

  PKG_ENTRY="`cat ${HOME}/.packages/Packages-* | grep "|$PKGNAME|"`"
  [ "$PKG_ENTRY" = '' ] && PKG_ENTRY="`cat ${HOME}/.packages/Packages-* | grep "|$PKGNAME_ONLY|"`"
  [ "$PKG_ENTRY" = '' ] && PKG_ENTRY="`cat ${HOME}/.packages/Packages-* | grep "^$PKGNAME|"`"
  if [ "$PKG_ENTRY" = '' ];then
    echo "$1 not found in $REPOFILE"
    exit 1
  else
    echo "$PKG_ENTRY" | tr '|' '\n' | grep -v '^$'
    exit 0
  fi
}


pkg_status(){                    # print package name, status, deps, etc FUNCLIST
  
  # exit if no valid options
  [ ! "$1" -o "$1" = "-" ] && print_usage pkg-status && exit 1
  
  # get current repo name
  . ${PKGRC}
  
  local EX
  local PKGNAME=''
  local PKGNAME_ONLY=''
  local PKGFILE=''
  local MSG=''
  local install_status=''
  local pkg_found=false
  local pkg_repo=''
  local pkg_repo_file=''
  local prev_repo=${REPONAME}
  
  # get pkg extension
  EX=`get_pkg_ext "$1"`

  # get pkg name with version, but no extension or path
  PKGNAME="$(basename "$1" .$EX)"
  
  # dont rely on the string the user gave us, try to get the exact match 
  PKGNAME=`get_pkg_name "$PKGNAME"`

  # get pkg name without version
  PKGNAME_ONLY=`get_pkg_name_only "$PKGNAME"`

  [ "$PKGNAME" = '' ] && error "Can't find $1" && exit 1
  
  # get install status of pkg (installed or not)
  [ "`is_installed_pkg $PKGNAME`" = true ] && install_status="installed" || install_status="not installed"

  # if pkg is installed, find out from where
  if [ "$install_status" = "installed" ];then
    
    # check user installed pkgs for $PKGNAME
    pkg_found=`LANG=C is_usr_pkg "${PKGNAME}"`
    [ "$pkg_found" = true ] && install_status="installed (user)"

    # if pkg not found yet, check if pkg is from the devx
    if [ -f ${HOME}/.packages/devx-only-installed-packages -a "$pkg_found" = false ];then
      pkg_found=`LANG=C is_devx_pkg "${PKGNAME}"`
      [ "$pkg_found" = true ] && install_status="installed (in devx)"
    fi
  
    # check builtins for PKGNAME_ONLY, if it exists, its a builtin pkg
    if [ -d ${HOME}/.packages/builtin_files/ -a "$pkg_found" = false ];then
      pkg_found=`LANG=C is_builtin_pkg "${PKGNAME_ONLY}"`
      [ "$pkg_found" = true ] && install_status="installed (builtin)"
    fi

    # last gasp, if pkg not found yet, check if pkg if listed in layers-installed packages
    if [ -f ${HOME}/.packages/layers-installed-packages -a "$pkg_found" = false ];then
      pkg_found=`LANG=C grep -m1 "^${PKGNAME}|" ${HOME}/.packages/layers-installed-packages`
      [ "$pkg_found" = '' ] && install_status="installed (layers)"
    fi

  fi

  # get the repo of this pkg, if needed
  [ "$pkg_repo" = '' ] && pkg_repo="`which_repo "$PKGNAME" | cut -f2 -d' '`"
  
  # if we got a repo name, get the repo file
  [ "$pkg_repo" != '' ] && pkg_repo_file="`repo_file_list $pkg_repo`"
  
  # if we have a repo to search for pkg info
  if [ "$pkg_repo_file" != "" ];then 

    # get package description from its repo entry
    pkg_desc="`LANG=C grep -m1 "|${PKGNAME_ONLY}|" $HOME/.packages/$pkg_repo_file 2>/dev/null| grep -m1 "$PKGNAME" | cut -f10 -d'|' | head -1`"
    
    # get size of pkg
    pkg_size=`LANG=C grep -m1 "|${PKGNAME_ONLY}|" $HOME/.packages/$pkg_repo_file 2>/dev/null | cut -f6 -d'|' | head -1`
    
    # add K to end of pkg_size, if not there already
    [ "$pkg_size" != '' ] && pkg_size="${pkg_size}K" && pkg_size="${pkg_size//KK/K}"
      
    # if called with -PS, we get the full info (where we sort deps missing or installed)
    if [ "$FULL_PKG_STATUS" = true ];then

      # if pkg has many deps, checking the deps might take a while, print a 'please wait' msg
      please_wait=false
      # count deps of pkg
      [ "`has_deps "$PKGNAME"`" = true ] && please_wait=true
      [ "$please_wait" = true ] && echo -ne "Please wait.. Gathering dependency information.\n"

      set_current_repo $pkg_repo 1>/dev/null
      # sort deps into 2 lists: missing deps and installed deps
      find_deps "$PKGNAME"
      set_current_repo $prev_repo 1>/dev/null
      
      # create a nicely formatted, coloured list of deps, green for installed, yellow for missing
      INSTALLED_DEPS_MSG="${green}`echo "${DEPS_INSTALLED}"|grep -v "^\$"| tr '\n' ','| sed -e "s#,\\$##" -e 's#,#, #g' | fold -w 60 -s | sed "s#\\n#\\t\\t\\n#g"`${endcolour}"
      MISSING_DEPS_MSG="${yellow}`echo "${DEPS_MISSING}"   |grep -v "^\$"| tr '\n' ','| sed -e "s#,\\$##" -e 's#,#, #g' | fold -w 60 -s`${endcolour}"
      
      DEPS_ENTRY="Installed deps: ${INSTALLED_DEPS_MSG:-None}
Missing deps:   ${MISSING_DEPS_MSG:-None}"

    else    
      
      DEPS_ENTRY="Dependencies:   `list_deps "$PKGNAME"`"
    
    fi

    #250613 added desc
    MSG="
Name:           ${PKGNAME}
Description:    `echo ${pkg_desc:-No description}|head -c 58`..
Size:           ${pkg_size:-Unknown}
Status:         ${install_status:-Unknown}
In Repo:        ${pkg_repo:-Not in any repos}
Repo file:      `basename ${pkg_repo_file:-Not in any repositories} 2>/dev/null`
$DEPS_ENTRY"
  
  fi
  
  # if not found in any repo, maybe a woof or alien (user-installed) package
  if [ "$MSG" = "" ];then #if nothing found in any repo

    PKGFILE="`list_downloaded_pkgs | grep -m1 "^$PKGNAME"`"

    # if the pkg is a downloaded file (in WORKDIR)
    if [ -f "$WORKDIR/$PKGFILE" ];then
      
      # get the file, and get its file size
      PKGFILE="$WORKDIR/${PKGFILE}"
      [ "$pkg_size" = '' ] && pkg_size="`du -s -k "$PKGFILE" | cut -f1`K"
      [ "$pkg_size" = '' ] && pkg_size="`grep -m1 "|${PKGNAME_ONLY}|" ${HOME}/.packages/*-installed-packages | cut -f6 -d'|' | head -1`"

      
      # create msg for downloaded pkgs
      MSG="Name:           ${PKGNAME}
Size:           ${pkg_size:-Unknown}
Status:         Downloaded
Note:           Downloaded package, not in any repo.
$DEPS_ENTRY"
    
    # else, search for exact match, then pkg-*, then pkg_*, then pkg* in installed pkgs
    elif [ "`grep -m1 "|${PKGNAME_ONLY}|" ${HOME}/.packages/user-installed-packages 2>/dev/null`"   \
      -o "`grep -m1 "^${PKGNAME}|" ${HOME}/.packages/user-installed-packages 2>/dev/null`"   \
      -o "`grep -m1 "^${PKGNAME}|" ${HOME}/.packages/*-installed-packages 2>/dev/null`"   \
      -o "`grep -m1 "^${PKGNAME}-" ${HOME}/.packages/*-installed-packages 2>/dev/null`" \
      -o "`grep -m1 "^${PKGNAME}_" ${HOME}/.packages/*-installed-packages 2>/dev/null`" \
      -o "`grep -m1 "^${PKGNAME}" ${HOME}/.packages/*-installed-packages 2>/dev/null`" ];then
      
      # get deps and size from its entry in user-installed-packages
      DEPS_ENTRY="Dependencies:   `grep -m1 "^$PKGNAME" ${HOME}/.packages/user-installed-packages | cut -f9 -d'|' | sed -e 's/,+/,/' -e 's/^+//' -e 's/,$//'`"
      [ "$DEPS_ENTRY" = '' ] && DEPS_ENTRY="Dependencies:   `grep -m1 "^$PKGNAME" ${HOME}/.packages/*-installed-packages | cut -f9 -d'|' | sed -e 's/,+/,/' -e 's/^+//' -e 's/,$//'`"
      pkg_size=`LANG=C grep -m1 "|$PKGNAME_ONLY|" $HOME/.packages/*-installed-packages | cut -f6 -d'|' | head -1`
      # add K to end of pkg_size, if not there already
      [ "$pkg_size" != '' ] && pkg_size="${pkg_size}K" && pkg_size="${pkg_size//KK/K}"      

      # create msg for user installed pkgs
      MSG="Name:      ${PKGNAME}
Size:           ${pkg_size:-Unknown}
Status:         ${install_status}
Repo:           Alien package, not in any repo.
$DEPS_ENTRY"
    
    else # pkg wasn't found, it's unknown to Pkg
      MSG="$PKGNAME not found. 
Here are some packages in other repos:"
      PLIST="`which_repo ${PKGNAME}`"
      [ "$PLIST" != "" ] && MSG="$MSG
$PLIST"
      # create msg for alien pkgs
      MSG="$MSG
Name:           ${PKGNAME}
Status:         ${install_status:-Unknown}
Repo:           Alien package, not in $REPONAME repo.
$DEPS_ENTRY"
    
    fi
  
  fi
  
  # print message
  if [ "$MSG" != "" ];then
    # now output the final msg
    echo -e "$MSG" | grep -v ^$
    menu_entry_msg "$PKGNAME"
    echo
  else
    not_found "${PKGNAME}"
    exit 1
  fi
}


which_pkg(){                     # find out which pkg FILE comes from FUNCLIST
  
  # exit if no valid opts
  [ ! "$1" -o "$1" = '-' -o "$1" = '' ] && print_usage which && exit 1
  
  local PKGNAME=''
  local PKG_FILE_LIST=''
  local FILENAME=''
  local FILENAME_ONLY=''
  local DIRNAME=''
  local builtins_without_busybox="`find ${HOME}/.packages/builtin_files/* -maxdepth 1 -type f | grep -v "/busybox"`"
  
  # get user input
  FILENAME="`basename "$1"`"
  FILENAME_ONLY="$FILENAME"
  DIRNAME="`dirname "$1"`"
  
  # if we don't have a file, the user probably gave a command, 
  # so lets check see
  if [ ! -f "$1" ];then
    # if we get a command, then that is our FILENAME
    cmd=`which "$1"`
    # if $cmd found, set FILENAME to $cmd (FILENAME now includes full path)
    [ "$cmd" != '' ] && FILENAME=$cmd && FILENAME_ONLY=`basename "$FILENAME"`
  fi
  
  # dont use relative paths
  [ "`echo "$DIRNAME" | grep "^\."`" != '' ] && DIRNAME=''
  
  # try user installed pkgs contents of $HOME/.packages/*.files
  
  # try '$dir/$file', returns filename (no path) of matching *.files
  [ "$PKG_FILE_LIST" = '' ] && PKG_FILE_LIST="`grep -l "$DIRNAME/$FILENAME\$" ${HOME}/.packages/*.files | sed "s#$HOME/.packages/##g"`"
  
  # try '$dir/$file_*' if needed
  [ "$PKG_FILE_LIST" = '' ] && PKG_FILE_LIST="`grep -l "$DIRNAME/${FILENAME}_" ${HOME}/.packages/*.files | sed "s#$HOME/.packages/##g"`"
  
  # try '$dir/$file-*' if needed
  [ "$PKG_FILE_LIST" = '' ] && PKG_FILE_LIST="`grep -l "$DIRNAME/${FILENAME}\-" ${HOME}/.packages/*.files | sed "s#$HOME/.packages/##g"`"
  
  # if we found a package, set the package name to the name of the *.files file that we got
  [ "$PKG_FILE_LIST" != '' ] && PKGNAME="`basename "$PKG_FILE_LIST" .files`"
  
  # maybe we got nothing from *.files.. check builtins/$1* for ' $FILENAME_ONLY', 
  # returns PKGNAME of the matching builtin

  # if needed, search inside builtin file lists (EXCEPT busybox) for ' $FILENAME_ONLY'
  [ "$PKG_FILE_LIST" = '' ] && [ "$PKGNAME" = "" ] \
    && PKGNAME="$(basename `grep -l "^ $FILENAME_ONLY\$" $builtins_without_busybox | sed "s#$HOME/.packages/builtin_files/##g"` 2>/dev/null)"

  # if that didn't work, search inside builtin file lists of busybox for ' $FILENAME_ONLY'
  [ "$PKG_FILE_LIST" = '' ] && [ "$PKGNAME" = "" ] \
    && PKGNAME="$(basename `grep -l "^ $FILENAME_ONLY\$" ${HOME}/.packages/builtin_files/busybox | sed "s#$HOME/.packages/builtin_files/##g"` 2>/dev/null)"

  # apps in ADRV sfs dont have their files listed in their $HOME/.packages/builtin_files/$pkgname.. so.. 
  
  
  # now check pkg names (not pkg contents) of builtins (EXCEPT busybox) for '$file'.. cos maybe we didnt find the file inside the file lists
  [ "$PKGNAME" = "" ] \
    && PKGNAME="`echo "$builtins_without_busybox" | grep -m1 "^${FILENAME_ONLY}\$" | sed "s#$HOME/.packages/builtin_files/##g" 2>/dev/null`"
    
  # now look for '$file' in user installed repo list
  [ "$PKGNAME" = "" ] \
    && PKGNAME="`cut -f1,2,8 -d'|' $HOME/.packages/user-installed-packages 2>/dev/null | sed -e "s/^/|/" -e "s/\$/|/" | grep -m1 "|$FILENAME_ONLY|" | cut -f2 -d'|'`"

  # also look for '$file' in user/woof/devx installed repo list
  [ "$PKGNAME" = "" ] \
    && PKGNAME="`cut -f1,2,8 -d'|' $HOME/.packages/*-installed-packages 2>/dev/null | sed -e "s/^/|/" -e "s/\$/|/" | grep -m1 "|$FILENAME_ONLY|" | cut -f2 -d'|'`"

  
  # we searched for an exact match in builtins, user installed, woof installed and devx pkgs, now try some fuzzier matches

  # try /$file_* in builtins
  [ "$PKGNAME" = "" ] \
    && PKGNAME="$(basename `grep -l " ${FILENAME_ONLY}_" ${HOME}/.packages/builtin_files/* | sed "s#$HOME/.packages/builtin_files/##g"` 2>/dev/null)"
  
  # try $file-* in builtins
  [ "$PKGNAME" = "" ] \
    && PKGNAME="$(basename `grep -l " ${FILENAME_ONLY}-" ${HOME}/.packages/builtin_files/* | sed "s#$HOME/.packages/builtin_files/##g"` 2>/dev/null)"

  # try $file.* in builtins
  [ "$PKGNAME" = "" ] \
    && PKGNAME="$(basename `grep -l " ${FILENAME_ONLY}\." ${HOME}/.packages/builtin_files/* | sed "s#$HOME/.packages/builtin_files/##g"` 2>/dev/null)"

  # try *file in builtin pkgs
  [ "$PKGNAME" = "" ] \
    && PKGNAME="$(basename `grep -l "${FILENAME_ONLY}"\$ ${HOME}/.packages/builtin_files/* | sed "s#$HOME/.packages/builtin_files/##g"` 2>/dev/null)"


  # if we still didnt find it, look in user installed package lists, for FILENAME
  [ "$PKGNAME" = "" ] \
    && PKGNAME=`cat ${HOME}/.packages/user-installed-packages \
      | cut -f1,2,8 -d '|' \
      | sed -e "s/^/|/" -e "s/\$/|/" \
      | grep -m1 "|${FILENAME_ONLY}|" \
      | cut -f2 -d'|'` 2>/dev/null
  
  # if we still didnt find it, look in all installed package lists, for FILENAME
  [ "$PKGNAME" = "" ] \
    && PKGNAME=`cat ${HOME}/.packages/*-installed-packages \
      | cut -f1,2,8 -d '|' \
      | sed -e "s/^/|/" -e "s/\$/|/" \
      | grep -m1 "|${FILENAME_ONLY}|" \
      | cut -f2 -d'|'` 2>/dev/null
  
  # if we still didnt find it, look in all installed package lists, for *FILENAME
  [ "$PKGNAME" = "" ] \
    && PKGNAME=`cat ${HOME}/.packages/*-installed-packages \
      | cut -f1,2,8 -d '|' \
      | sed -e "s/^/|/" -e "s/\$/|/" \
      | grep -m1 "${FILENAME_ONLY}|" \
      | cut -f2 -d'|'` 2>/dev/null  
  
  # if we still didnt find it, look in all installed package lists, for FILENAME*
  [ "$PKGNAME" = "" ] \
    && PKGNAME=`cat ${HOME}/.packages/*-installed-packages \
      | cut -f1,2,8 -d '|' \
      | sed -e "s/^/|/" -e "s/\$/|/" \
      | grep -m1 "|${FILENAME_ONLY}" \
      | cut -f2 -d'|'` 2>/dev/null
  

  # clean up
  [ "$PKGNAME" = '.files' ] && PKGNAME=''
  PKGNAME="`echo "$PKGNAME" | head -1`"

  # now print pkgs which contain the given file ($1)
  if [ "$PKGNAME" != "" ];then
    echo "$PKGNAME"
    return 0
  else
    echo "File '$FILENAME' not found in any installed or built-in pkgs."
    exit 1
  fi
}


list_downloaded_pkgs(){          # list packages downloaded in WORKDIR
  
  . ${PKGRC}
  
  cd "$WORKDIR" || { error "Cant cd into $WORKDIR"; exit 3; }
  
  local pkg
  
  # if no pkg given, list all
  if [ ! "$1" ];then

    # get all pkgs in WORKDIR
    find "${WORKDIR}" -maxdepth 1 -type f | sed -e "s#${WORKDIR}##g" -e "s#^/##g" | grep -v ^'.pkg' | sort \
      | while read pkg # but go through each and only print it if a valid pkg
      do
        [ "`is_local_pkg "$pkg"`" = true ] && echo $pkg || continue
      done

    return 0
  
  else

    # $1 might be a pkg, or list of pkgs, loop through them
    for x in $1; do 
      if [ "$x" != "-" ];then 

        # print the list of packages matching $x
        find "${WORKDIR}" -maxdepth 1 -type f | sed -e "s#${WORKDIR}##g" -e "s#^/##g" | grep -v ^'.pkg'|grep ^"$x" | sort \
          | while read pkg # but go through each and only print it if a valid pkg
          do
            [ "`is_local_pkg "$pkg"`" = true ] && echo $pkg || continue
          done

        return 0
      fi
    done
  fi
  
  cd -
}


list_installed_pkgs(){           # list user installed packages

  local user_pkgs_list=''
  local builtins_list=''
  local devx_pkgs_list=''
  
  user_pkgs_list=${HOME}/.packages/user-installed-packages

  if [ "$HIDE_BUILTINS" != true -a -f ${HOME}/.packages/devx-only-installed-packages ];then
    devx_pkgs_list=${HOME}/.packages/devx-only-installed-packages
  fi

  [ "$HIDE_BUILTINS" != true ] && builtins_list=${HOME}/.packages/woof-installed-packages
  
  # search current repo file only .. $1 is the optional pkg filter.. take field1, remove empty lines, remove dashes, remove Pkg from pkg list too
  cut -f1 -d'|' $user_pkgs_list $devx_pkgs_list $builtins_list | grep "^$1" | grep -v ^\$  | grep -v "\-$" | grep -v ^pkg\- | uniq
}


list_builtin_pkgs(){             # list builtin packages

  local builtins_repo
  
  builtins_repo=${HOME}/.packages/woof-installed-packages

  # search builtins (woof-installed) repo file only .. $1 is the optional pkg filter.. take field1, remove empty lines, remove dashes, remove Pkg from pkg list too
  cut -f1 -d'|' $builtins_repo | grep "^$1" | grep -v ^\$  | grep -v "\-$" | grep -v ^pkg\- | sort
}


pkg_download(){                  # download a pkg to WORKDIR FUNCLIST
  
  # exit if no valid options
  [ ! "$1" -o "$1" = "-" ] && print_usage download && exit 1
  
  . ${PKGRC}
  
  local pkg_ext=''        # the extension of the given pkg, empty if not a supported pkg ext
  local PKGNAME=''    # the pkgname with version
  local ORIG_PKGNAME='' # keeps the original pkg name ($1)
  local PKG_FILENAME='' # package file name (field 8 of repo, with extension)
  local PKGFILE=''    # full path to package file
  local NET=''      # 1 or 0 if net connection available
  local curr_repo=''    # name of current repo in the loop
  local curr_repo_ext=''  # pkg ext for the current repo in the loop
  local prev_repo_url=''  # holder for the prev checked url we know is working
  local curr_repo_url=''  # mirror that is used to download the pkg
  local curr_repo_url1='' # mirror1 for the current repo in the loop
  local curr_repo_url2='' # mirror2 for the current repo in the loop
  local curr_repo_url3='' # mirror3 for the current repo in the loop
  local curr_repo_url4='' # mirror4 for the current repo in the loop
  local pkg_in_repo=''  # true if pkg found in ANY repo, else false
  
  # get pkg extension
  pkg_ext=`get_pkg_ext "$1"`
  
  # get pkg name with version (if given!), no extension or path
  PKGNAME="$(basename "$1" .$pkg_ext)" 
  
  # get full package name from given pkg name string .. vlc -> vlc-1.2.3-blah
  PKGNAME=`get_pkg_name "$PKGNAME"`
  
  # the file to save to.. not reliable till we checked the repos
  PKGFILE="${WORKDIR}/${PKGNAME}.$pkg_ext"
  
  # set download options
  [ "$FORCE" = true  ] && CONTINUE='' || CONTINUE='-c'
  [ "${ASK}" != true ] && QTAG=''
  
  #if pkg not yet downloaded, or we are downloading all, or we are forcing downloads
  if [ ! -f "$PKGFILE" -o "$NO_INSTALL" = true -o "$FORCE" = true ];then
    
    # mark this pkg as not yet downloaded
    DONE=false

    # exit if no internet connection
    #NET="`check_net`"; [ $NET -eq 1 ] && echo "You need an internet connection" && exit 2
    
    # for each repo, starting with current repo 
    list_sources_files | while read repo_file
    do

      # the file with our repo URL info
      sources_file="${HOME}/.pkg/sources"

      # check if $repo_file contains the given pkg
      pkg_in_this_repo="`LANG=C cut -f1,2,7,8 -d'|' ${HOME}/.packages/$repo_file 2>/dev/null | sed -e "s/^/|/" -e "s/$/|/" | grep -m1 "|${PKGNAME}|"`"
      [ "$pkg_in_this_repo" = '' ] && pkg_in_this_repo="`LANG=C cut -f1,2,7,8 -d'|' ${HOME}/.packages/$repo_file 2>/dev/null | sed -e "s/^/|/" -e "s/$/|/" | grep -m1 "|${PKGNAME}"`"
      
      # if package file found in current repo file
      if [ "$pkg_in_this_repo" != "" ];then #if true, its an exact match

        # get name of current repo in loop
        prev_repo="$curr_repo" 
        curr_repo="`LANG=C grep $repo_file $sources_file 2>/dev/null | cut -f1 -d'|'`" 

        # get ext of cur repo, it might be different
        curr_repo_ext="`LANG=C grep $repo_file $sources_file 2>/dev/null| cut -f2 -d'|'`"  

        # keep a copy of the PKGNAME we got from `get_pkg_name $1`
        ORIG_PKGNAME=$PKGNAME
        
        # get proper PKGNAME (inc name-ver) from the repo
        PKGNAME="`echo "$pkg_in_this_repo" | cut -f3 -d'|'`"
        # just in case it didn't work, revert back to the old PKGNAME value
        [ "$PKGNAME" = "" ] && PKGNAME="$ORIG_PKGNAME"

        # get full pkg FILENAME (inc name-ver.ext) from the repo
        PKG_FILENAME="`echo "$pkg_in_this_repo" | cut -f5 -d'|'`"
      
        # just in case its empty, revert back to the earlier PKGNAME value
        [ "$PKG_FILENAME" = "" ] && PKG_FILENAME="$PKGNAME"

        # update the filename to check/download
        PKGFILE="${WORKDIR}/${PKG_FILENAME}"

        # skip if downloaded already, print msg
        [ -f "$PKGFILE" ] && DONE=true && echo -e "Already downloaded ${magenta}${PKG_FILENAME}${endcolour}" && continue

        # update the package name, based on PKG_FILENAME
        PKGNAME="$(basename "$PKG_FILENAME" .$curr_repo_ext)"
        
        # update generic name
        PKGNAME_ONLY="`get_pkg_name_only "$PKGNAME"`"

        if [ "${PKG_FILENAME}" = '' ];then
          error "Cant find pkg file name, needed to download"
          return 1
        fi
        
        # skip pings and download if already downloaded.. unless forcing download
        if [ ! -f "$PKGFILE" -o "$FORCE" = true ];then
        
          # ask user to download
          echo -en "Download ${magenta}${PKGNAME_ONLY}${endcolour} from ${lightblue}${curr_repo}${endcolour} repo$QTAG:  " 
          [ "${ASK}" = true ] && read -n 1 CONFIRM </dev/tty || CONFIRM=y
          [ "$CONFIRM" != 'y' ] && echo

          # if user answered yes, we will now download the pkgs
          if [ "$CONFIRM" = "y" ];then #25073

            echo # start a new line

            # get the subdir (from repo line) that the package lives in
            sub_dir="`echo "$pkg_in_this_repo" | cut -f4 -d'|'`"

            # pre-woof get subdir
            if [ -f "$HOME/.packages/${repo_file}_subdirs" ];then
              sub_dir="`grep -m1 "^$PKGNAME|" "$HOME/.packages/${repo_file}_subdirs"  2>/dev/null | cut -f7 -d'|'`"
            fi

            # get repo mirrors (only url1 is required .. we also add a final /)
            curr_repo_url1="`LANG=C grep $repo_file $sources_file 2>/dev/null| cut -f4 -d'|'`/" 
            curr_repo_url2="`LANG=C grep $repo_file $sources_file 2>/dev/null| cut -f5 -d'|'`/" 
            curr_repo_url3="`LANG=C grep $repo_file $sources_file 2>/dev/null| cut -f6 -d'|'`/" 
            curr_repo_url4="`LANG=C grep $repo_file $sources_file 2>/dev/null| cut -f7 -d'|'`/" 
            
            # make a space separated list of all our repo URLs
            curr_repo_url_list="$curr_repo_url1 $curr_repo_url2 $curr_repo_url3 $curr_repo_url4" 
            
            # clean up the list, remove any double slashes at the end of each URL
            curr_repo_url_list="`echo "$curr_repo_url_list" | sed -e "s|// |/ |g" -e "s|//\$|/\$|g"`"
            
            # update the ext to that of current repo
            pkg_ext="$curr_repo_ext" 
            
            # get the best repo mirror
            #if [ "$prev_repo" != "$current_repo"  -a -f $TMPDIR/curr_repo_url ] || [ ! -f $TMPDIR/curr_repo_url ];then
              #echo "Checking '$curr_repo' repo mirrors..."
              for URL in $curr_repo_url_list
              do
                LANG=C ping -W2 -c1 -q `echo  ${URL} | awk -F/ '{print $3}'` &>/dev/null
                REPLY=$?
                if [ "$REPLY" = 0 ];then
                  # set the current URL
                  curr_repo_url="$URL"
                  echo "$curr_repo_url" > $TMPDIR/curr_repo_url
                  break
                fi
              done
            #else
            # curr_repo_url="`cat $TMPDIR/curr_repo_url`"
            #fi

            # lets build our DOWNLOAD_URL: set it to the working repo mirror we found above
            DOWNLOAD_URL="${curr_repo_url}"
            
            # now add the subdir to DOWNLOAD_URL .. sub_dir may be empty, but we add a trailing '/' anyway
            DOWNLOAD_URL="${DOWNLOAD_URL}${sub_dir}/"
            
            # add some system values into the repo URL (arch, distro version, etc.. from DISTRO_SPECS)
            DOWNLOAD_URL="`echo "$DOWNLOAD_URL"| sed -e 's@${DBIN_ARCH}@'$DBIN_ARCH'@g'`"
            DOWNLOAD_URL="`echo "$DOWNLOAD_URL"| sed -e 's@${DISTRO_COMPAT_VERSION}@'$DISTRO_COMPAT_VERSION'@g'`"
            DOWNLOAD_URL="`echo "$DOWNLOAD_URL"| sed -e 's@${DDB_COMP}@'$DDB_COMP'@g'`"
            
            # add our package to the URL
            DOWNLOAD_URL="${DOWNLOAD_URL}${PKG_FILENAME}"
            
            # remove any double forward slashes (the main URL or subdir may have ended in slashes, it may not, we added our own to be sure)
            DOWNLOAD_URL="`echo "$DOWNLOAD_URL"| sed -e "s@//$PKG_FILENAME@/$PKG_FILENAME@g"`"
            
            # if sub_dir not empty, lets clean that bit too
            [ "$sub_dir" != '' ] && DOWNLOAD_URL="`echo "$DOWNLOAD_URL"| sed -e "s@//${sub_dir}@/${sub_dir}@g" -e "s@${sub_dir}//@${sub_dir}/@g"`"
            
            # exit if URL is not found (if we get a 404 back)
            if [ "`wget -S --spider $DOWNLOAD_URL 2>&1 | grep 'HTTP/1.1 404 Not Found'`" != '' ]; then
              error "Package URL not found"
              return 8
            fi
 
            # we may be using multiple URLs, so each time we change URL,
            #  remember the new one
            if [ "$OLDURL" != "$DOWNLOAD_URL" ];then
              export OLDURL="$DOWNLOAD_URL";
              #echo -e "URL: ${lightblue}${DOWNLOAD_URL}${endcolour}"; 
            fi
            
            # if --force, remove the package if it already exists
            [ "$FORCE" = true ] && rm -f "${WORKDIR}/${PKG_FILENAME}" &>/dev/null
            
            # if file not downloaded, or forcing downloads
            if [ ! -f "${WORKDIR}/${PKG_FILENAME}" -o "$FORCE" = true ];then

              # BEGIN DOWNLOAD file here.. 

              # print DOWNLOADING msg
              echo -en "Downloading ${magenta}${PKG_FILENAME}${endcolour}. Please wait:     "
              
              # if called as 'gpkg', give a pop GUI (uses Xdialog) showing download progress..
              # can be used by X apps to easily start (and show!) downloads
              if [ "$SELF" = "gpkg" ];then 
                
                download_progress "$DOWNLOAD_URL" "${WORKDIR}/${PKG_FILENAME}" 2>/dev/null
                
              else # if called as 'pkg', dont use Xdialog, output to terminal

                if [ "$QUIET" = true ];then
                  echo
                  echo -n "Downloading now..."
                  LANG=C wget \
                    --no-check-certificate \
                    --progress=dot -O "${WORKDIR}/${PKG_FILENAME}" \
                    -4 $CONTINUE "$DOWNLOAD_URL" &>/dev/null
                else
                  # START DOWNLOAD, show percentage as we go
                  LANG=C wget \
                    --no-check-certificate \
                    --progress=dot -O "${WORKDIR}/${PKG_FILENAME}" \
                    -4 $CONTINUE "$DOWNLOAD_URL" 2>&1 \
                    | grep --line-buffered "%" \
                    | sed -u -e "s#\.##g" \
                    | awk '{printf("\b\b\b\b%4s", $2)}' #220613
                fi
                
              fi
            
            fi # end if WORKDIR/PKG not a file or FORCE=true
            
            # clean up output
            [ "$QUIET" != true ] && echo -ne "\b\b\b\b"
            echo

            # if file downloaded ok
            if [ -f "${WORKDIR}/${PKG_FILENAME}" ];then
              echo -e "${green}Downloaded:${endcolour} ${WORKDIR}/${PKG_FILENAME}"
              DONE=true
              break
            
            else # file NOT downloaded ok
            
              error "Failed to download '${WORKDIR}/${PKG_FILENAME}'."
              echo "Check '$DOWNLOAD_URL'"

              # remove the page we tried to get pkg from (if exists)
              rm "${WORKDIR}/index.html" &>/dev/null
              DONE=true
              exit 6
            fi

          fi # end if CONFIRM=y

          # user chose not to do anything
          DONE=true
          break
        
        else # Already downloaded, skip to next iteration
          
          #echo "Package $1 already downloaded"
          DONE=true
          break
        fi

      else # no repo match, nothing to download
        
        # go to next repo, try to ge tthe pkg there
        DONE=false 
        
      fi # end if repo match was found

      # if download not successful, keep going to next repo
      [ "$DONE" = true ] && continue

    done #done while read list of repo files
    
  fi
}


pkg_install(){                   # install a downloaded package FUNCLIST

  . ${PKGRC}
  
  # exit if no valid option
  [ ! "$1" -o "$1" = "-" ] && print_usage install && exit 1
  
  # skip if not installing pkgs
  [ "$NO_INSTALL" = true ] && continue
  
  local pkg_ext
  local PKGNAME
  local PKGNAME_ONLY
  local PKGFILE 
  local PREVDIR="$CURDIR"
  local petspecs

  # get pkg extension
  pkg_ext=`get_pkg_ext "$1"`
  # get pkg name only, no extension or path
  PKGNAME="$(basename "$1" .$pkg_ext)" 
  # get name without version  
  PKGNAME_ONLY=`get_pkg_name_only "$PKGNAME"`

  # exit if no valid option
  [ "$PKGNAME" = '' ] && print_usage install && exit 1

  [ "`is_installed_pkg "$PKGNAME"`" = true -a "$FORCE" = false ] && echo "Already installed: $PKGNAME" && return 1

  if [ -f "$1" ];then
    PKGFILE="$1"
    PKGNAME=`basename "$1" .$pkg_ext`
  else
    # get the real file name (inc path) from the given PKGFILE and pkg_ext (which may be empty)
    PKGFILE=`find "$CURDIR" -maxdepth 1 -type f -name "${PKGNAME}*${pkg_ext}" | head -1`
    [ ! -f "$PKGFILE" ] && PKGFILE=`find "$CURDIR" -maxdepth 1 -type f -name "${PKGNAME}*${EX}" | grep -m1 $EX`
    [ -f "$PKGFILE" ] && PKGNAME=`basename "$1" .$pkg_ext`
  fi
  
  # maybe the file is not in the current dir, but in WORKDIR, so lets look there too
  if [ ! -f "$PKGFILE" ];then
    PKGFILE=`find "$WORKDIR" -maxdepth 1 -type f -name "${PKGNAME}*${pkg_ext}" | head -1`
    [ ! -f "$PKGFILE" ] && PKGFILE=`find "$WORKDIR" -maxdepth 1 -type f -name "${PKGNAME}*${EX}" | grep -m1 $EX`

    # if we found the file in WORKDIR, make that our CURDIR
    if [ -f "$PKGFILE" ];then
      PKGNAME=`basename "$PKGFILE" .$pkg_ext`
      CURDIR="$WORKDIR"
      cd "$WORKDIR"
    else
      # if we still didn't find it, do a broader check
      PKGFILE=`find "$WORKDIR" -maxdepth 1 -type f -name "${PKGNAME}*" | head -1`
      if [ -f "$PKGFILE" ];then
        PKGNAME=`basename "$PKGFILE" .$pkg_ext`
        CURDIR="$WORKDIR"
        cd "$WORKDIR"
      fi
    fi
  fi

  # if the file exists, or using --force
  if [ -f "$PKGFILE" -o "$FORCE" = true ];then
  
    [ ! -f "$PKGFILE" ] && echo "The file $1 was not found." && return 1

    # get the extension of this newly found pkg (which we should have found by now)
    pkg_ext=`get_pkg_ext "$PKGFILE"`
    # get extension again, we may have been given only a pkg name, find its extension from repo files
    [ "$pkg_ext" = "" ] && pkg_ext=`get_pkg_ext "$PKGNAME"`
    
    [ "$pkg_ext" = '' ] && echo "Not installing $PKGFILE." && error "Invalid file extension ($pkg_ext)." && return 1

    # remove any previous PET/pkg stuff lying around from previous installs
    rm -f /pet.specs /pinstall.sh /puninstall.sh /install/doinst.sh

    # if pkg is not yet installed, or we are force re-installing

    # get filename from download file
    PKGNAME=`basename "$PKGFILE" .$pkg_ext`

    # ask/inform user before install
    echo -n "Install package ${PKGNAME}$QTAG:  "
    [ "$ASK" = true ] && read -n 1 CONFIRM </dev/tty || CONFIRM=y
    [ "$ASK" = true ] && echo -ne "\b\b\n"
    
    # if user answered yes, we will now download the pkgs
    if [ "$CONFIRM" = "y" ];then

      # print new line if we didnt take any user input on tty
      [ "$ASK" != true ] && echo
      
      #if [ "`pkg_contents "$PKGFILE" 2>/dev/null`" = '' ];then
      # error "$PKGFILE not a valid package."
      # exit 1
      #fi

      # fallback to repo pkg ext if none found
      [ "$pkg_ext" = "" ] && pkg_ext="$EX"
      
      #remove the old error log
      rm $TMPDIR/$SELF-cp-errlog 2>/dev/null

      # extract the archive file into a $CURDIR/$PKGNAME folder
      case "$pkg_ext" in
        
        pet) 
          PKGFILE="`find ${CURDIR} -type f -name "${PKGNAME}*.pet"`"
          #determine the compression, extend test to 'XZ'
          file -b "${PKGFILE}" | grep -i -q "^xz" && TAREXT=xz || TAREXT=gz
          [ "$TAREXT" = 'xz' ] && taropts='-xJf' || taropts='-zxf'
          
          # convert to tar extractable archive
          pet2tgz "${PKGFILE}" 1>/dev/null
          
          # now extract the file
          tar $taropts "${CURDIR}/${PKGNAME}.tar.${TAREXT}" 2> $TMPDIR/$SELF-cp-errlog

          # some old types need this extra step
          if [ -f "${CURDIR}/${PKGNAME}.tar.$TAREXT" ];then
            cd "${CURDIR}/${PKGNAME}/" 1>/dev/null
            tar --absolute-names $tarops "./${PKGNAME}.tar.$TAREXT" ${DIRECTSAVEPATH}/ 2> $TMPDIR/$SELF-cp-errlog #260713
            sync
            rm -f  "./${PKGNAME}.tar.$TAREXT" 1>/dev/null
            cd - 1>/dev/null
          fi

          # save the uninstall script for later
          if [ -f "${CURDIR}/${PKGNAME}/puninstall.sh" ];then
            mv "${CURDIR}/${PKGNAME}/puninstall.sh" ${HOME}/.packages/${PKGNAME}.remove
          fi
          
          # create a tgz
          tgz2pet "${CURDIR}/${PKGNAME}.tar.$TAREXT" 1>/dev/null
          rm "${CURDIR}/${PKGNAME}.tar.$TAREXT" 2>/dev/null
        ;;
        
        sfs) 
          sfs_loadr -q --cli +"${CURDIR}/${PKGNAME}.${pkg_ext}" #2>/dev/null
          rm -f $HOME/.packages/${PKGNAME}.files 2>/dev/null
          # create $HOME/.packages/$PKGNAME.files
          pkg_contents "${CURDIR}/${PKGNAME}.${pkg_ext}" | while read line
          do
            [ -f "$line" ] && echo "$line" >> $HOME/.packages/${PKGNAME}.files
          done
          # exit, we dont need to unpack and copy
          return 0
        ;;
        
        deb) 

          rmdir "${CURDIR}/${PKGNAME}" &>/dev/null
          mkdir -p "${CURDIR}/${PKGNAME}"
          [ ! -f "$PKGFILE" ] && PKGFILE="`find ${CURDIR} -type f -name "${PKGNAME}*.deb"`"
          cp "${PKGFILE}" "${CURDIR}/${PKGNAME}/${PKGNAME}.deb" || exit 4
          cd "${CURDIR}/${PKGNAME}/"

          if [ -f "${CURDIR}/${PKGNAME}.deb" ];then
            dpkg-deb --contents ${CURDIR}/${PKGNAME}.deb | grep -v '/$' | tr -s ' ' | cut -f6 -d' ' | sed -e 's/^.//g' | grep -v '^$' > $HOME/.packages/${PKGNAME}.files
          fi

          pkg_has_archdir="$(grep -m1 "$DISTRO_ARCHDIR" "$HOME/.packages/${PKGNAME}.files")"

          # Workaround to avoid overwriting the $DISTRO_ARCHDIR symlink.  
          if [ "$DISTRO_ARCHDIR" != "" -a -f $HOME/.packages/${PKGNAME}.files -a "$pkg_has_archdir" != "" ]; then
             mkdir -p /tmp/$PKGNAME
             rm -rf /tmp/$PKGNAME/*
             dpkg-deb -x ${CURDIR}/${PKGNAME}.deb /tmp/$PKGNAME/ 2> $TMPDIR/$SELF-cp-errlog
             for f in $(find /tmp/$PKGNAME \( -type f -o -type l \))
             do
             xpath=$(echo "$f" |  cut  -f 4-30 -d "/" | sed "s/$DISTRO_ARCHDIR\///")
             mkdir -p ${DIRECTSAVEPATH}/$(dirname "$xpath")
             cp -a "$f" ${DIRECTSAVEPATH}/$(dirname "$xpath")/
            done
            rm -rf /tmp/$PKGNAME &>/dev/null
          else
             dpkg-deb -x ${CURDIR}/${PKGNAME}.deb ${DIRECTSAVEPATH}/ 2> $TMPDIR/$SELF-cp-errlog
          fi

          if [ "`cat $TMPDIR/$SELF-cp-errlog | grep 'tar: Exiting with failure status due to previous errors'`" != "" ];then
            error "Failed to unpack $PKGNAME.deb"
            exit 1
          fi
          [ -d /DEBIAN ] && rm -rf /DEBIAN #130112 precaution.
          dpkg-deb -e ${CURDIR}/${PKGNAME}.deb /DEBIAN #130112 extracts deb control files to dir /DEBIAN. may have a post-install script, see below.
          rm "${PKGNAME}.deb"
          cd - 1>/dev/null
        ;;
        
        *tbz|*tar.bz2) 
          rmdir "${CURDIR}/${PKGNAME}" &>/dev/null
          mkdir -p "${CURDIR}/${PKGNAME}" 
          cp "${CURDIR}/${PKGNAME}.$pkg_ext" "${CURDIR}/${PKGNAME}/${PKGNAME}.$pkg_ext" || exit 4
          cd "${CURDIR}/${PKGNAME}/"
          
          ( umask 000 ; cat "${PKGNAME}.$pkg_ext" | bzip2 -dc | tar -xf - 2> $TMPDIR/$SELF-cp-errlog )
          
          rm "${PKGNAME}.$pkg_ext"
          cd - 1>/dev/null
        ;;
        
        *tlz|*tar.lzma) 
          rmdir "${CURDIR}/${PKGNAME}" &>/dev/null
          mkdir -p "${CURDIR}/${PKGNAME}" 
          PKGFILE="`find ${CURDIR} -type f -name "${PKGNAME}*.${pkg_ext}"`"
          cp "$PKGFILE" "${CURDIR}/${PKGNAME}/`basename $PKGFILE`" || exit 4
          cd "${CURDIR}/${PKGNAME}/"
          
          ( umask 000 ; cat "${PKGNAME}.$pkg_ext" | lzma -dc | tar -xf - 2> $TMPDIR/$SELF-cp-errlog )
          
          rm "${PKGNAME}.$pkg_ext"
          cd - 1>/dev/null
        ;;
        
        *tgz|*txz|*tar.gz|*tar.xz|*xz|*gz) 
          rmdir "${CURDIR}/${PKGNAME}" &>/dev/null
          mkdir -p "${CURDIR}/${PKGNAME}" 
          PKGFILE="`find ${CURDIR} -type f -name "${PKGNAME}*.${pkg_ext}"`"
          cp "$PKGFILE" "${CURDIR}/${PKGNAME}/`basename $PKGFILE`" || exit 4
          cd "${CURDIR}/${PKGNAME}/"
          
          file -b "${PKGNAME}.$pkg_ext" | grep -i -q "^xz" && TAREXT=xz || TAREXT=gz
          [ "$TAREXT" = 'xz' ] && taropts='-xJf' || taropts='-zxf'
          
          tar $taropts "${PKGNAME}.$pkg_ext" 2> $TMPDIR/$SELF-cp-errlog
          rm "${PKGNAME}.$pkg_ext"
          cd - 1>/dev/null
        ;;
        
        rpm)
          PKGNAME="`basename ${PKGFILE} .rpm`"
          busybox rpm -qp "$PKGFILE" > /dev/null 2>&1
          [ $? -ne 0 ] && exit 1
          PFILES="`busybox rpm -qpl $PKGFILE`"
          [ $? -ne 0 ] && exit 1
          echo "$PFILES" > $HOME/.packages/${PKGNAME}.files
          pkg_unpack "$PKGFILE" 1>/dev/null
        ;;
      
      esac

      # now extract pkg contents to /
      [ ! -d "${PKGNAME}/" ] && error "Cannot enter directory '${PKGNAME}/', it doesn't exist." && exit 4
      cd "${PKGNAME}/" 1>/dev/null

      cp -a --remove-destination * ${DIRECTSAVEPATH}/ 2> $TMPDIR/$SELF-cp-errlog

      #source is a directory, target is a symlink...
      if [ -s $TMPDIR/$SELF-cp-errlog ];then
        cat $TMPDIR/$SELF-cp-errlog  2>/dev/null | grep -E 'Cannot create symlink to|cannot overwrite non-directory' | cut -f 1 -d "'" | cut -f 2 -d '`' |
        while read ONEDIRSYMLINK
        do
          #adding that extra trailing / does the trick...
          cp -a --remove-destination ${ONEDIRSYMLINK}/* /${ONEDIRSYMLINK}/ 2> $TMPDIR/$SELF-cp-errlog #260713
        done
      fi
      sync
      cd .. 1>/dev/null
        
      if [ ! -f $HOME/.packages/${PKGNAME}.files ];then
        # add ${HOME}/.packages/${PKGNAME}.files, need to find regular files and links separately... then images..
        find "./${PKGNAME}/" -mount -mindepth 2 -type f | sed -e "s/\.\/${PKGNAME}//g" -e 's/\/root0\//\/root\//g' > $HOME/.packages/${PKGNAME}.files
        find "./${PKGNAME}/" -mount -mindepth 2 -type l | sed -e "s/\.\/${PKGNAME}//g" -e 's/\/root0\//\/root\//g' >> $HOME/.packages/${PKGNAME}.files

        for ONEIMAGEFILE in `ls -1 /*[0-9].xpm 2>/dev/null`
        do
         BASEONEIMAGE="`basename $ONEIMAGEFILE`"
         echo "/usr/local/lib/X11/pixmaps/$BASEONEIMAGE" >> $HOME/.packages/${PKGNAME}.files
        done
        for ONEIMAGEFILE in `ls -1 /*[0-9].png 2>/dev/null`
        do
         BASEONEIMAGE="`basename $ONEIMAGEFILE`"
         echo "/usr/local/lib/X11/pixmaps/$BASEONEIMAGE" >> $HOME/.packages/${PKGNAME}.files
        done
        for ONEIMAGEFILE in `ls -1 /*[^0-9].xpm 2>/dev/null`
        do
         BASEONEIMAGE="`basename $ONEIMAGEFILE`"
         echo "/usr/local/lib/X11/mini-icons/$BASEONEIMAGE" >> $HOME/.packages/${PKGNAME}.files
        done
        for ONEIMAGEFILE in `ls -1 /*[^0-9].png 2>/dev/null` #v2.16
        do
         BASEONEIMAGE="`basename $ONEIMAGEFILE`"
         echo "/usr/local/lib/X11/mini-icons/$BASEONEIMAGE" >> $HOME/.packages/${PKGNAME}.files
        done
      fi
        
      # move the *.files to $HOME/.packages 
      FILES=''
      FILES="`find "$CURDIR" -iname "*.files" | head -1`"
      [ -f "`echo $FILES`" ] && mv "$FILES" "${HOME}/.packages/" 2>/dev/null #260713

      #pkgname.files may need to be fixed...
      cat ${HOME}/.packages/${PKGNAME}.files | grep -v '/$' | sed -e 's%^\\.%%' -e 's%^%/%' -e 's%^//%/%' > ${HOME}/.packages/${PKGNAME}.files2
      mv ${HOME}/.packages/${PKGNAME}.files2 ${HOME}/.packages/${PKGNAME}.files

      sort -u $HOME/.packages/${PKGNAME}.files > $HOME/.packages/${PKGNAME}.files2
      mv ${HOME}/.packages/${PKGNAME}.files2 ${HOME}/.packages/${PKGNAME}.files

      # some pets add images and icons at / so move them
      mv /{*.xpm,*.png} /usr/share/pixmaps/ 2>/dev/null
      mv /*.ico /usr/share/pixmaps/ 2>/dev/null

      # run the post install scripts (for puppy, slackware, arch, debian/ubuntu, etc)
      for i in /pinstall.sh /install/doinst.sh /DEBIAN/postinst
      do
        [ -z /${i} -o ! -e /${i} ] && continue
        chmod +x /${i}
        cd /
        nohup sh ${i} &>/dev/null
        sleep 0.2
        rm -f ${i}
        cd ${CURDIR}/
      done
      rm -rf /install
      rm -rf /DEBIAN

      #130314 run arch linux pkg post-install script...
      if [ -f /.INSTALL -a /usr/local/petget/ArchRunDotInstalls ];then #precaution. see 3builddistro, script created by noryb009.
        #this code is taken from below...
        dlPATTERN='|'"`echo -n "${PKGNAME}" | sed -e 's%\\-%\\\\-%'`"'|'
        archVER="`cat $TMPDIR/petget_missing_dbentries-Packages-* 2>/dev/null | grep "$dlPATTERN" | head -n 1 | cut -f 3 -d '|'`"
        if [ "$archVER" ];then #precaution.
          cd /
          mv -f .INSTALL .INSTALL1-${archVER}
          cp -a /usr/local/petget/ArchRunDotInstalls ArchRunDotInstalls
          LANG=$LANG_USER ./ArchRunDotInstalls
          rm -f ArchRunDotInstalls
          rm -f .INSTALL*
          cd ${CURDIR}/
        fi
      fi

      PKGCAT=''
      PKGSIZE=''
      PKGDESC=''
      DEPLIST=''

      # clean up pet installs 
      if [ "$pkg_ext" = "pet" ];then
        cd /

        # get pkg info from pet.spec before we delete it, because the PET may not be a repo pkg
        petspecs="`cat /pet.specs 2>/dev/null`"
        
        if [ "$petspecs" != '' ];then
          # now get pkg info
          PKGCAT="`echo $petspecs|  cut -f5  -d'|'`"
          PKGSIZE="`echo $petspecs| cut -f6  -d'|'`"
          PKGDESC="`echo $petspecs| cut -f10 -d'|'`"
          DEPSLIST="`echo $petspecs|cut -f9  -d'|'`"
        fi

        cd ${CURDIR}/
      fi

      # cleanup a bit 
      rm -R "${PKGNAME}/" 2>/dev/null || echo "${yellow}Warning:${endcolour} Cannot remove directory '${PKGNAME}/'." #150213

      #120102 install may have overwritten a symlink-to-dir...
      #tar defaults to not following symlinks, for both dirs and files, but i want to follow symlinks
      #for dirs but not for files. so, fix here... (note, dir entries in .files have / on end)
      cat ${HOME}/.packages/${PKGNAME}.files | grep '[a-zA-Z0-9]/$' | sed -e 's%/$%%' | grep -v '^/mnt' |
      while read ONESPEC
      do
       if [ -d "${DIRECTSAVEPATH}${ONESPEC}" ];then
        if [ ! -h "${DIRECTSAVEPATH}${ONESPEC}" ];then
         DIRLINK=""
         if [ -h "/initrd${PUP_LAYER}${ONESPEC}" ];then #120107
        DIRLINK="`readlink -m "/initrd${PUP_LAYER}${ONESPEC}" | sed -e "s%/initrd${PUP_LAYER}%%"`" #PUP_LAYER: see /etc/rc.d/PUPSTATE. 120107
        xDIRLINK="`readlink "/initrd${PUP_LAYER}${ONESPEC}"`" #120107
         fi
         if [ ! "$DIRLINK" ];then
        if [ -h "/initrd${SAVE_LAYER}${ONESPEC}" ];then #120107
         DIRLINK="`readlink -m "/initrd${SAVE_LAYER}${ONESPEC}" | sed -e "s%/initrd${SAVE_LAYER}%%"`" #SAVE_LAYER: see /etc/rc.d/PUPSTATE. 120107
         xDIRLINK="`readlink "/initrd${SAVE_LAYER}${ONESPEC}"`" #120107
        fi
         fi
         if [ "$DIRLINK" ];then
        if [ -d "$DIRLINK"  ];then
         if [ "$DIRLINK" != "${ONESPEC}" ];then #precaution.
          mkdir -p "${DIRECTSAVEPATH}${DIRLINK}" #120107
          cp -a -f --remove-destination ${DIRECTSAVEPATH}"${ONESPEC}"/* "${DIRECTSAVEPATH}${DIRLINK}/" #ha! fails if put double-quotes around entire expression.
          rm -rf "${DIRECTSAVEPATH}${ONESPEC}"
          if [ "$DIRECTSAVEPATH" = "" ];then
           ln -s "$xDIRLINK" "${ONESPEC}"
          else
           DSOPATH="`dirname "${DIRECTSAVEPATH}${ONESPEC}"`"
           DSOBASE="`basename "${DIRECTSAVEPATH}${ONESPEC}"`"
           rm -f "${DSOPATH}/.wh.${DSOBASE}" #allow underlying symlink to become visible on top.
          fi
         fi
        fi
         fi
        fi
       fi
      done

      #121217 it seems that this problem is occurring in other modes (13 reported)...
      #121123 having a problem with multiarch symlinks in full-installation...
      #it seems that the symlink is getting replaced by a directory.
      if [ "$DISTRO_ARCHDIR" ];then #in /etc/rc.d/DISTRO_SPECS. 130112 change test from DISTRO_ARCHDIR. 130114 revert DISTRO_ARCHDIR_SYMLINKS==yes.
        if [ -d /usr/lib/${DISTRO_ARCHDIR} ];then
         if [ ! -h /usr/lib/${DISTRO_ARCHDIR} ];then
        cp -a -f --remove-destination /usr/lib/${DISTRO_ARCHDIR}/* /usr/lib/
        sync
        rm -r -f /usr/lib/${DISTRO_ARCHDIR}
        ln -s ./ /usr/lib/${DISTRO_ARCHDIR}
         fi
        fi
        if [ -d /lib/${DISTRO_ARCHDIR} ];then
         if [ ! -h /lib/${DISTRO_ARCHDIR} ];then
        cp -a -f --remove-destination /lib/${DISTRO_ARCHDIR}/* /lib/
        sync
        rm -r -f /lib/${DISTRO_ARCHDIR}
        ln -s ./ /lib/${DISTRO_ARCHDIR}
         fi
        fi
        if [ -d /usr/bin/${DISTRO_ARCHDIR} ];then
         if [ ! -h /usr/bin/${DISTRO_ARCHDIR} ];then
        cp -a -f --remove-destination /usr/bin/${DISTRO_ARCHDIR}/* /usr/bin/
        sync
        rm -r -f /usr/bin/${DISTRO_ARCHDIR}
        ln -s ./ /usr/bin/${DISTRO_ARCHDIR}
         fi
        fi
      fi

      #flush unionfs cache, so files in pup_save layer will appear "on top"...
      if [ "$DIRECTSAVEPATH" != "" ];then
       #but first, clean out any bad whiteout files...
       # 22sep10 shinobar: bugfix was not working clean out whiteout files
       find /initrd/pup_rw -mount -type f -name .wh.\*  -printf '/%P\n'|
       while read ONEWHITEOUT
       do
        ONEWHITEOUTFILE="`basename "$ONEWHITEOUT"`"
        ONEWHITEOUTPATH="`dirname "$ONEWHITEOUT"`"
        if [ "$ONEWHITEOUTFILE" = ".wh.__dir_opaque" ];then
         [ "`grep "$ONEWHITEOUTPATH" /root/.packages/${PKGNAME}.files`" != "" ] && rm -f "/initrd/pup_rw/$ONEWHITEOUT"
         continue
        fi
        ONEPATTERN="`echo -n "$ONEWHITEOUT" | sed -e 's%/\\.wh\\.%/%'`"'/*' ;#echo "$ONEPATTERN" >&2
        [ "`grep -x "$ONEPATTERN" /root/.packages/${PKGNAME}.files`" != "" ] && rm -f "/initrd/pup_rw/$ONEWHITEOUT"
       done
       #111229 /usr/local/petget/removepreview.sh when uninstalling a pkg, may have copied a file from sfs-layer to top, check...
       cat ${HOME}/.packages/${PKGNAME}.files |
       while read ONESPEC
       do
        [ "$ONESPEC" = "" ] && continue #precaution.
        if [ ! -d "$ONESPEC" ];then
         [ -e "/initrd/pup_rw${ONESPEC}" ] && rm -f "/initrd/pup_rw${ONESPEC}"
        fi
       done
       #now re-evaluate all the layers...
       busybox mount -t aufs -o remount,udba=reval unionfs / #remount with faster evaluation mode.
       [ $? -ne 0 ] && logger -s -t "pkg" "Failed to remount aufs / with udba=reval"
       sync
      fi

      # get pkg size, category and description
      [ "$PKGCAT" = ''  ] && PKGCAT=`LANG=C  grep -m1 "|${PKGNAME_ONLY}|" "${HOME}/.packages/${REPOFILE}" 2>/dev/null | cut -f5 -d'|' | head -1`
      [ "$PKGCAT" = ''  ] && PKGCAT=`LANG=C  grep -m1 "^${PKGNAME}|" "${HOME}/.packages/${REPOFILE}" 2>/dev/null | cut -f5 -d'|' | head -1`
      [ "$PKGDESC" = '' ] && PKGDESC=`LANG=C grep -m1 "|${PKGNAME_ONLY}|" "${HOME}/.packages/${REPOFILE}" 2>/dev/null| cut -f10 -d'|' | head -1`
      [ "$PKGDESC" = '' ] && PKGDESC=`LANG=C grep -m1 "^${PKGNAME}|" "${HOME}/.packages/${REPOFILE}" 2>/dev/null| cut -f10 -d'|' | head -1`
      [ "$PKGSIZE" = '' ] && PKGSIZE=`LANG=C du -s -k ${CURDIR}/${PKG} 2>/dev/null | cut -f1`
      # get pkg version
      PKGVER="`LANG=C  echo "$PKGNAME" | sed -e 's/^[^0-9]*-//g'`"
      PKGARCH="`LANG=C echo "$PKGNAME" | cut -f3 -d'-' | grep -E 'i[3-9]|x[8-9]|noarch'`"

      # last check for pkg info
      [ "$DEPSLIST" = '' ] && DEPSLIST="`grep -m1 "^${PKGNAME}|" ${HOME}/.packages/Packages-* 2>/dev/null | cut -f9 -d'|' | grep '+' | head -1`"
      [ "$PKGDESC" = ''  ] && PKGDESC="No description"

      #080917 - build woof compatible repo line .. #090817
      if [ "`cut -f1 -d'|' ${HOME}/.packages/user-installed-packages 2>/dev/null | grep -m1 ^${PKGNAME}`" = '' ];then

        # get the package db entry to add to user-installed-packages...
        # first, get it from petspecs if possible, or from the pkgs repo, or make one
        if [ -f /pet.specs ];then
          DB_ENTRY="`cat /pet.specs | head -n 1`"
        elif [ "`grep -m1 "^${PKGNAME}|" "${HOME}/.packages/$REPOFILE"`" != "" ];then
          DB_ENTRY="`grep -m1 "^${PKGNAME}|" "${HOME}/.packages/$REPOFILE"`"
        else 
          DB_ENTRY="${PKGNAME}|${PKGNAME_ONLY}|${PKGVER}|${BUILD}|${PKGCAT}|${PKGSIZE}|${PKGDIR}|${PKGNAME}.${pkg_ext}|${DEPSLIST}|${PKGDESC}|${DISTRO_BINARY_COMPAT}|${DISTRO_COMPAT_VERSION}"
        fi

        # Fix for Debian executables showing as shared libs in ROX.
        if [ "$DISTRO_FILE_PREFIX" = "stretch" -o "$DISTRO_FILE_PREFIX" = "ascii" ]; then
          if [ "$(ps aux | grep ROX |grep -v grep)" ]; then # Other managers are OK
            if [ "$(which elfedit)" ];then
              grep -E '/bin/|/sbin/' ${HOME}/.packages/${PKGNAME}.files |
              while read FLINE
              do
                [ "$(file "$FLINE" | grep -i 'shared object')" ] && elfedit --input-type=dyn --output-type=exec $FLINE
              done
            else
              echo -e "${yellow}Warning${endcolour} Recent Debian executables show as shared libraries in ROX,"
              echo "which causes ROX to fail to open or execute them. To fix that during package "
              echo "installation you should install elfutils or have devx loaded."
            fi
          fi
        fi

        # now add the db entry to user-installed-packages
        echo "$DB_ENTRY" >> ${HOME}/.packages/user-installed-packages #130913
      
      fi

      # now delete the petspecs file(s), we already added our PKG info to installed-packages
      rm /pet.specs &>/dev/null 
      rm /*.pet.specs &>/dev/null 
      
      # make sure /tmp has correct permission, a pkg may have overwritten it
      ls -dl /tmp | grep -q '^drwxrwxrwt' || chmod 1777 /tmp #130305 rerwin.
      
      #090817
      if [ "`is_installed_pkg $PKGNAME`" = true -a "`cat $HOME/.packages/${PKGNAME}.files`" != '' ];then
        echo -e "${green}Installed:${endcolour} $PKGNAME"
        # show if pkg has menu entry
        menu_entry_msg "$PKGNAME_ONLY" 
        #080413 do fixmenus, if menu entry found #200713 moved here
        if [ "`grep -m1 '/usr/share/applications' $HOME/.packages/${PKGNAME}.files 2>/dev/null | grep desktop$`" != "" ];then
          [ ! -f /tmp/pkg/update_menus_busy ] && update_menus &
        fi
        [ "`which logger`" != '' ] && logger "$0 Package $PKGNAME installed by $APP $APPVER"
      else
        error "$PKGNAME may not have installed correctly."
      fi
      
      #100817 clean up user-installed-packages (remove duplicates and empty lines
      cat ${HOME}/.packages/user-installed-packages | grep -v "^\$" | uniq > ${HOME}/.packages/user-installed-packages_clean
      mv ${HOME}/.packages/user-installed-packages_clean ${HOME}/.packages/user-installed-packages
      
      # puppy specific fixes for installed package
      postinstall_hacks "$PKGNAME" "$PKGNAME_ONLY" &

      #100622 slackware 13.1: just in case any got through, remove c-shell scripts...
      rm -f /etc/profile.d/*.csh* 2>/dev/null

      #120523 precise puppy needs this... (refer also rc.update and 3builddistro)
      if [ "`grep '/usr/share/glib-2.0/schemas' $HOME/.packages/${PKGNAME}*.files 2>/dev/null`" != "" ];then
        [ -e /usr/bin/glib-compile-schemas ] && /usr/bin/glib-compile-schemas /usr/share/glib-2.0/schemas &>/dev/null
      fi

      if [ "`grep '/usr/lib/gio/modules' $HOME/.packages/${PKGNAME}.files 2>/dev/null`" != "" ];then
        [ -e /usr/bin/gio-querymodules ] && /usr/bin/gio-querymodules /usr/lib/gio/modules &>/dev/null
      fi
      
      sync
        
    fi #if CONFIRM = y #100213,0.9  moved down to here, fixes install, and output msgs

  else # file doesn't exists, user must download it first
    
    if [ "$PKGNAME" != '' ];then

      echo "Package '$PKGNAME' not yet downloaded."

      matching_local_pkgs="`list_downloaded_pkgs $PKGNAME`"

      # if no matching pkgs downloaded
      if [ "$matching_local_pkgs" != "" ];then    
        echo "You could install one of the following packages with \`$SELF -i PKGNAME\`:"
        echo "`list_downloaded_pkgs $(basename "$PKGNAME" .$pkg_ext 2>/dev/null) 2>/dev/null`"
      
      # else if not downloaded, and in the current repo, list the matching repo pkgs
      elif [ "$matching_local_pkgs" = "" -a "`grep -m1 "^${PKGNAME}|" "${HOME}/.packages/${REPOFILE}" 2>/dev/null`" != "" ];then
        echo "You must first download one of the following packages with \`$SELF -d PKGNAME\`:"
        echo "`$PKGSEARCH $(basename $PKGNAME .$pkg_ext)`"
      
      else
        not_found "${PKGNAME}"
      fi
    
    else # PKGNAME is empty
    
      echo "Package could not be identified."

    fi
    
    exit 1

  fi

  # go back to the dir we started in
  cd "$PREVDIR"

}


postinstall_hacks(){             # fix pkgs after installation
local PKGNAME="$1"
local PKGNAME_ONLY="$2"

# remove %u, %U, %f (etc) from Exec lines
DESKTOPFILE="`find /usr/share/applications -iname "${PKGNAME_ONLY}*.desktop"`"
[ -f "$DESKTOPFILE" ] && \
  sed -i 's/ %u//' $DESKTOPFILE && \
  sed -i 's/ %U//' $DESKTOPFILE && \
  sed -i 's/ %f//' $DESKTOPFILE && \
  sed -i 's/ %F//' $DESKTOPFILE
  
case $PKGNAME in
 0ad-*|0ad_*)
  bbe -e 's/geteuid/getppid/' /usr/games/pyrogenesis > /usr/games/pyrogenesis1 2>/dev/null
  mv /usr/games/pyrogenesis1 /usr/games/pyrogenesis
  chmod 755 /usr/games/pyrogenesis
 ;;
 openclonk-*|openclonk_*)
  bbe -e 's/geteuid/getppid/' /usr/games/openclonk > /usr/games/openclonk1 2>/dev/null
  mv /usr/games/openclonk1 /usr/games/openclonk
  chmod 755 /usr/games/openclonk
 ;;
 vlc_*|vlc-*)
  VLCDESKTOP="`find /usr/share/applications -mindepth 1 -maxdepth 1 -iname 'vlc*.desktop'`"
  [ -f $VLCDESKTOP ] && sed -i 's/ --started-from-file %U//' $VLCDESKTOP
  [ -f $VLCDESKTOP ] && sed -i 's/ --started-from-file//' $VLCDESKTOP

  #120907 vlc in debian/ubuntu configured to not run as root (it is a pre-compile configure option to enable running as root).
  #this hack will fix it...
  #note, this code is also in FIXUPHACK in 'vlc' template.
  if [ -f /usr/bin/bbe ];then #bbe is a sed-like utility for binary files.
   if [ -f /usr/bin/vlc  ];then
     bbe -e 's/geteuid/getppid/' /usr/bin/vlc > /tmp/vlc-temp1
     mv -f /tmp/vlc-temp1 /usr/bin/vlc
     chmod 755 /usr/bin/vlc
   fi
  fi
 ;;
 google-chrome-*) #130221 pemasu. 130224 pemasu: limit cache size...
  if [ -f /usr/bin/bbe ];then #bbe is a sed-like utility for binary files.
   if [ -f /opt/google/chrome/chrome  ];then
  bbe -e 's/geteuid/getppid/' /opt/google/chrome/chrome > /tmp/chrome-temp1
  mv -f /tmp/chrome-temp1 /opt/google/chrome/chrome
  chmod 755 /opt/google/chrome/chrome
  [ -e /usr/bin/google-chrome ] && rm -f /usr/bin/google-chrome
  echo '#!/bin/sh
exec /opt/google/chrome/google-chrome --user-data-dir=/root/.config/chrome --disk-cache-size=10000000 --media-cache-size=10000000 "$@"' > /usr/bin/google-chrome
  chmod 755 /usr/bin/google-chrome
  ln -s google-chrome /usr/bin/chrome
  ln -s /opt/google/chrome/product_logo_48.png /usr/share/pixmaps/google-chrome.png
  ln -s /opt/google/chrome/product_logo_48.png /usr/share/pixmaps/chrome.png
  CHROMEDESKTOP="`find /usr/share/applications -mindepth 1 -maxdepth 1 -iname '*chrome*.desktop'`"
  if [ "$CHROMEDESKTOP" = "" ];then #precaution.
   echo '[Desktop Entry]
Encoding=UTF-8
Version=1.0
Name=Google Chrome web browser
GenericName=Google Chrome
Comment=Google Chrome web browser
Exec=google-chrome
Terminal=false
Type=Application
Icon=google-chrome.png
Categories=WebBrowser;' > /usr/share/applications/google-chrome.desktop
  fi
   fi
  fi
 ;;
chromium*) #130221 pemasu. 130224 pemasu: limit cache size...
  if [ -f /usr/bin/bbe ];then #bbe is a sed-like utility for binary files.
   if [ -f /usr/lib/chromium/chromium  ];then
  bbe -e 's/geteuid/getppid/' /usr/lib/chromium/chromium > /tmp/chrome-temp1
  mv -f /tmp/chrome-temp1 /usr/lib/chromium/chromium
  chmod 755 /usr/lib/chromium/chromium
  [ -e /usr/bin/chromium ] && rm -f /usr/bin/chromium
  echo '#!/bin/sh
exec /usr/lib/chromium/chromium --user-data-dir=/root/.config/chrome --disk-cache-size=10000000 --media-cache-size=10000000 --audio-buffer-size=2048 "$@"' > /usr/bin/chromium
  chmod 755 /usr/bin/chromium
  ln -s /usr/share/icons/hicolor/48x48/apps/chromium.png /usr/share/pixmaps/chromium.png
  CHROMEDESKTOP="`find /usr/share/applications -mindepth 1 -maxdepth 1 -iname '*chromium-br*.desktop'`"
  if [ "$CHROMEDESKTOP" = "" ];then #precaution.
   echo '[Desktop Entry]
Encoding=UTF-8
Version=1.0
Name=Chromium web browser
GenericName=Chromium
Comment=Chromium web browser
Exec=chromium
Terminal=false
Type=Application
Icon=chromium.png
Categories=WebBrowser;' > /usr/share/applications/chromium.desktop
  fi
   fi
  fi
 ;;
 jwm_theme_*)
  #120924 DejaVu font no good for non-Latin languages...
  #see also langpack_* pinstall.sh (template is in /usr/share/doc/langpack-template/pinstall.sh, read by momanager).
  LANGUSER="`grep '^LANG=' /etc/profile | cut -f 2 -d '=' | cut -f 1 -d ' '`"
  case $LANGUSER in
   zh*|ja*|ko*) #chinese, japanese, korean
  sed -i -e 's%DejaVu Sans%Sans%' /etc/xdg/templates/_root_*
  sed -i -e 's%DejaVu Sans%Sans%' /root/.jwm/themes/*-jwmrc
  sed -i -e 's%DejaVu Sans%Sans%' /root/.jwm/jwmrc-theme
   ;;
  esac
  #130326 font size fix for 96 dpi...
  if [ "$PKGNAME_ONLY" ];then
   JWMTHEMEFILE="$(grep '^/root/\.jwm/themes/.*-jwmrc$' /root/.packages/${PKGNAME_ONLY}.files | head -n 1)"
   [ "$JWMTHEMEFILE" ] && hackfontsize "JWMTHEMES='${JWMTHEMEFILE}'"
  fi
 ;;
 openbox*)
  #120924 DejaVu font no good for non-Latin languages...
  #see also langpack_* pinstall.sh (template is in /usr/share/doc/langpack-template/pinstall.sh, read by momanager).
  LANGUSER="`grep '^LANG=' /etc/profile | cut -f 2 -d '=' | cut -f 1 -d ' '`"
  case $LANGUSER in
   zh*|ja*|ko*) #chinese, japanese, korean
  sed -i -e 's%DejaVu Sans%Sans%' /etc/xdg/openbox/*.xml
  sed -i -e 's%DejaVu Sans%Sans%' /root/.config/openbox/*.xml
   ;;
  esac
 ;;
 gtk_theme_*)
  #120924 DejaVu font no good for non-Latin languages...
  #see also langpack_* pinstall.sh (template is in /usr/share/doc/langpack-template/pinstall.sh, read by momanager).
  LANGUSER="`grep '^LANG=' /etc/profile | cut -f 2 -d '=' | cut -f 1 -d ' '`"
  case $LANGUSER in
   zh*|ja*|ko*) #chinese, japanese, korean
  GTKRCFILE="$(find /usr/share/themes -type f -name gtkrc | tr '\n' ' ')"
  for ONEGTKRC in $GTKRCFILE
  do
   sed -i -e 's%DejaVu Sans%Sans%' $ONEGTKRC
  done
   ;;
  esac
  #130326 font size fix for 96 dpi...
  if [ "$PKGNAME_ONLY" ];then
   GTKTHEMEFILE="$(grep '^/usr/share/themes/.*/gtk-2\.0/gtkrc$' /root/.packages/${PKGNAME_ONLY}.files | head -n 1)"
   [ "$GTKTHEMEFILE" ] && hackfontsize "GTKRCS='${GTKTHEMEFILE}'"
  fi
 ;;
 seamonkey*|firefox*)
  #120924 DejaVu font no good for non-Latin languages...
  #see also langpack_* pinstall.sh (template is in /usr/share/doc/langpack-template/pinstall.sh, read by momanager).
  LANGUSER="`grep '^LANG=' /etc/profile | cut -f 2 -d '=' | cut -f 1 -d ' '`"
  case $LANGUSER in
   zh*|ja*|ko*) #chinese, japanese, korean
  MOZFILE="$(find /root/.mozilla -type f -name prefs.js -o -name '*.css' | tr '\n' ' ')"
  for ONEMOZ in $MOZFILE
  do
   sed -i -e 's%DejaVu Sans%Sans%' $ONEMOZ
  done
   ;;
  esac
 ;;
 mc_*) #121206 midnight commander
  #in ubuntu, won't run from the menu. this fixes it...
  [ -f /usr/share/applications/mc.desktop ] && sed -i -e 's%^Exec=.*%Exec=TERM=xterm mc%' /usr/share/applications/mc.desktop
 ;;
 xsane*) #130122
  #xsane puts up a warning msg at startup if running as root, remove it...
  #this code is also in file FIXUPHACK in xsane template (in Woof).
  #WARNING: this may only work for x86 binary.
  if [ -f /usr/bin/bbe ];then #bbe is a sed-like utility for binary files.
   if [ -f /usr/bin/xsane  ];then
  bbe -e 's/\x6b\x00getuid/\x6b\x00getpid/' /usr/bin/xsane > /tmp/xsane-temp1
  mv -f /tmp/xsane-temp1 /usr/bin/xsane
  chmod 755 /usr/bin/xsane
   fi
  fi
 ;;
 kompozer*) #130507
  [ -f /usr/bin/kompozer ] && [ -d /usr/lib/kompozer ] && sed -i -e 's%^moz_libdir=%export MOZILLA_FIVE_HOME="/usr/lib/kompozer" #BK\nmoz_libdir=%' /usr/bin/kompozer
 ;;
esac
}


pkg_uninstall(){                 # remove an installed package FUNCLIST
  
  # quit if no valid options
  [ ! "$1" -o "$1" = "-" ] && print_usage uninstall && exit 1

  local PKGNAME
  local PKGNAME_ONLY
  local PKGFILE
  local pkg_ext
  
  # get pkg extension
  pkg_ext=`get_pkg_ext "$1"`
  
  #get pkg name with version, but no extension or path 
  PKGNAME="$(basename "$1" .$pkg_ext)" 
  PKGNAME=`get_pkg_name "$PKGNAME"`

  # get pkg name only .. without versions or suffix
  PKGNAME_ONLY="`get_pkg_name_only "$PKGNAME"`"
  
  local pkg_is_builtin=`is_builtin_pkg "$PKGNAME_ONLY"`
  local is_installed=`is_installed_pkg "$PKGNAME"`
  
  # skip pkg if its a builtin
  [ "$pkg_is_builtin" = true ] && return 1
  
  # if pkg is SFS, "uninstall" it here and quit
  if [ "`sfs_loadr -q -i | grep -v ^sfs_loadr | grep ^$PKGNAME`" -o "$pkg_ext" = "sfs" ];then
    sfs_loadr -q --cli -"${CURDIR}/${PKGNAME}" && rm -f $PKGFILE #2>/dev/null
    return 0
  fi
  

  if [ "$is_installed" = true -o "$FORCE" = true ];then #250713

    # get the list of files to be deleted, exact match
    PKGFILE="`find ${HOME}/.packages/ -maxdepth 1 -type f -name "$PKGNAME.files"`"

    # if no exact match, search for pkgname*
    [ ! -f "$PKGFILE" ] && PKGFILE="`find ${HOME}/.packages/ -maxdepth 1 -type f -name "${PKGNAME}*.files"`"
    
    #if PKG.files not found, then remove it from alien packages list 
    if [ ! -f "$PKGFILE" ];then

      error "'${PKGNAME}.files' not found.. Cleaning up.."

      # backup the original list of user installed pkgs
      cp ${HOME}/.packages/user-installed-packages $TMPDIR/user-installed-packages.backup
      
      # remove $PKGNAME from list of installed pkgs
      cat ${HOME}/.packages/user-installed-packages 2>/dev/null | grep -v "^${PKGNAME}" > ${HOME}/.packages/user-installed-packages.updated
      
      # if we created a new file ok
      if [ -f ${HOME}/.packages/user-installed-packages.updated ];then
        # replace the user-installed-packages file with our new one
        mv ${HOME}/.packages/user-installed-packages.updated ${HOME}/.packages/user-installed-packages 2>/dev/null
      fi

      # clean up user-installed-packages (remove duplicates and empty lines)
      cat ${HOME}/.packages/user-installed-packages | grep -v "^\$" | uniq > ${HOME}/.packages/user-installed-packages.clean
      mv ${HOME}/.packages/user-installed-packages.clean ${HOME}/.packages/user-installed-packages

      # no *.files to process, so if not forcing full uninstall, we can exit here
      [ "$FORCE" = false ] && return 1
    fi

    # if we are here, we have a $HOME/.packages/***.files to work with (or using --force)
    
    # get pkgs that depend on $PKGNAME
    [ "$FORCE" = false ] && dependents="`list_dependents "$PKGNAME"`" || dependents=''

    # if we have dependents, we should not uninstall and just exit, unless --force was given
    if [ "$dependents" != "" -a "`echo "$dependents" | grep 'not installed'`" = '' -a "$FORCE" != true ];then
    
      # inform user of dependent pkgs
      echo -e "${yellow}Warning${endcolour}: $PKGNAME_ONLY is needed by:  "
      echo -e "${magenta}$dependents${endcolour}"
      echo "Uninstall the packages above first, or use:"
      echo -e "${bold}pkg --force uninstall $PKGNAME${endcolour}."
      echo
      return 1
    
    fi
      
    # ask/inform user before uninstall 
    echo -n "Uninstall the package ${PKGNAME}$QTAG:  "
    [ "$ASK" = true ] && read -n 1 CONFIRM </dev/tty || CONFIRM=y
    [ "$ASK" = true ] && echo -ne "\b\b\n"
    
    # if user answered yes, we will now uninstall the pkgs
    if [ "$CONFIRM" = "y" ];then
      
      # print new line if we didnt take any user input on tty
      [ "$ASK" != true ] && echo
      
      # execute uninstall script.
      if [ -x "${HOME}/.packages/${PKGNAME}.remove" ];then
        ${HOME}/.packages/${PKGNAME}.remove &>/dev/null
        rm -f ${HOME}/.packages/${PKGNAME}.remove &>/dev/null
      fi
      
      # if we have no pkg file (listing of pkg contents), we cant cat/grep it
      if [ ! -f "$PKGFILE" ];then
        echo "Not found: $HOME/.packages/$PKGNAME.files"
        return 1
      fi
      
      # check if has menu entry
      [ "`cat "$PKGFILE" | grep -m1 ".desktop\$"`" != "" ] && HASMENUENTRY=true || HASMENUENTRY=false
      
      # remove files listed in *.files
      cat "$PKGFILE" | while read LINE
      do 
        # some symlinks may not get removed. '-e' will not work if symlink
        # is pointing to a non-existent file. So, check for symlink...
        REMFILE=""
        [ -h "$LINE" ] && REMFILE="yes"
        [ -e "$LINE" ] && REMFILE="yes"
        if [ "$REMFILE" = "yes" ];then
          if [ ! -d "$LINE" ];then
            if [ -e "/initrd/pup_ro2$LINE" ];then
              # deleting the file on the top layer places a ".wh" whiteout file, that hides the original file.
              # what we want is to remove the installed file, and restore the original pristine file...
              cp -af "/initrd/pup_ro2${LINE}" "$LINE"
            else
              rm -f "$LINE" &>/dev/null
            fi
            #delete empty dirs...
            DELDIR="`dirname "$LINE" 2>/dev/null`"
            [ "`ls -1 "$DELDIR"`" = "" ] && rmdir "$DELDIR" &>/dev/null
          fi
        fi
      done

      # go through again and remove any empty dirs...
      cat "$PKGFILE" 2>/dev/null  | while read LINE
      do
        DELDIR="`dirname "$LINE" 2>/dev/null`"
        [ -d "$DELDIR" ] && [ "`ls -1 "$DELDIR"`" = "" ] && rmdir "$DELDIR"
        #check one level up... but do not delete top dir, like /opt...
        DELLEVELS=`echo -n "$DELDIR" | sed -e 's/[^/]//g' | wc -c | sed -e 's/ //g'`
        if [ $DELLEVELS -gt 2 ];then
          DELDIR="`dirname "$DELDIR" 2>/dev/null`"
          [ -d "$DELDIR" ] && [ "`ls -1 "$DELDIR"`" = "" ] && rmdir $DELDIR
        fi
      done
      
      # remove $PKGNAME from user-installed-packages
      NEWUSERPKGS="`grep -v "^${PKGNAME}" ${HOME}/.packages/user-installed-packages`"
      [ "$NEWUSERPKGS" != "" ] && echo "$NEWUSERPKGS" > ${HOME}/.packages/user-installed-packages
      
      # clean up user-installed-packages (remove duplicates and empty lines)
      cat ${HOME}/.packages/user-installed-packages | grep -v "^\$" | uniq > ${HOME}/.packages/user-installed-packages_clean
      mv ${HOME}/.packages/user-installed-packages_clean ${HOME}/.packages/user-installed-packages

      # remove $HOME/.packages/$PKGNAME.files
      rm $PKGFILE ${PKGFILE} 2>/dev/null
      
      # do fixmenus, if menu entry found
      if [ "$HASMENUENTRY" = true ];then
        [ ! -f /tmp/pkg/update_menus_busy ] && update_menus &
      fi
      
      # UNINSTALL DONE .. print message
      echo -e "${green}Uninstalled:${endcolour} $PKGNAME"
      
      # log uninstall with the system logs
      [ "`which logger`" != '' ] && logger "$0 Package $PKGNAME uninstalled by $APP $APPVER"

    fi #end if $CONFIRM=yes

  else # $PKGNAME is not installed

    # if any installed pkg matches $PKGNAME
    if [ "`list_installed_pkgs $PKGNAME`" != "" ];then #290613
      # list the matching pkgs
      echo "These installed packages match '$PKGNAME':"
      echo "`list_installed_pkgs $PKGNAME`"
    fi

    return 1
    
  fi # endif installed or not
}


pkg_get(){                       # find, download and install packages and deps FUNCLIST
  
  # The function `choose_pkg` is run just before this one. It gives us $TMPDIR/USRPKGLIST,
  # which contains a list of packages the user wants to install or download.
  # In this func, we will go through the list and download/install the package, as well 
  # as its dependencies (depending on what the user chose to do).

  . ${PKGRC}
  
  # exit if no valid options
  [ ! "$1" -o "$1" = "" -o "$1" = "-" ] && print_usage get && exit 1
  
  local PREVDIR="$CURDIR"
  local pkg_ext=`get_pkg_ext "$1"`; pkg_ext="${pkg_ext:-$EX}" # fall back to repo extension
  local PKGNAME="`get_pkg_name $(basename "$1" .$pkg_ext)`"
  local PKGNAME_ONLY=`get_pkg_name_only "$PKGNAME"`
  local PKGLIST="${PKGNAME}"
  local pkg_builtin=''

  # exit if no valid pkg name
  [ ! "$PKGNAME" -o "$PKGNAME" = "" -o "$PKGNAME" = "-" ] && print_usage get && exit 1
  
  # we want to download all pkgs to same place
  cd "$WORKDIR"
  CURDIR="$WORKDIR"

  # use the list of pkgs user has chosen to install, or the given PKGNAME
  if [ "`cat "$TMPDIR/USRPKGLIST" 2>/dev/null`" != "" ];then
    PKGLIST="`cat "$TMPDIR/USRPKGLIST" | grep -v "^\$"`"
  fi
  
  if [ -z "$PKGLIST" ];then
    echo "No packages to get, exiting."
    exit 1
  fi
  
  # skip if any pkgs previously installed during our current loop (of getting 'pkg + recursive deps')
  echo "$PKGLIST" | while read pkg_in_list
  do
    name_only=`get_pkg_name_only "$pkg_in_list"`
    [ -f $TMPDIR/PKGSDONE -a "`grep "^${name_only}\$" $TMPDIR/PKGSDONE 2>/dev/null`" != '' ] && continue
  done
  
  # list the pkgs and ask to download (and maybe install)
  echo "$PKGLIST" | while read pkg
  do

    [ "$pkg" = '' -o ! "$pkg" ] && continue
    
    local pkg_name=`get_pkg_name "$pkg" 2>/dev/null`

    [ "$pkg_name" = '' -o ! "$pkg_name" ] && continue

    local pkg_name_only=`get_pkg_name_only "$pkg"`
    local pkg_already_done=`grep -m1 "^$pkg_name_only\$" $TMPDIR/PKGSDONE 2>/dev/null`
    # dont install this package is if already in PKGSDONE
    [ "$pkg_already_done" != '' ] && continue

    local pkg_in_repo=`is_repo_pkg $pkg_name_only`
    local PKGFILE=''

    # dont even try to download if no matches found
    if [ "$pkg_in_repo" = true -a "$pkg_name_only" != "" ];then 
      
      local pkg_is_builtin=`is_builtin_pkg "$pkg_name_only"`
      local pkg_is_in_devx=`is_devx_pkg "$pkg_name_only"`

      # skip getting pkg if its a builtin, unless HIDE_BUILTINS=false
      if [ "$pkg_is_builtin" = true -a "${HIDE_BUILTINS}" = true ];then
        echo "Skipping $pkg_name_only (already built-in).."
        continue
      fi

      # skip getting pkg if its in the devx, unless HIDE_BUILTINS=false
      if [ "$pkg_is_in_devx" = true -a "${HIDE_BUILTINS}" = true ];then
        echo "Skipping $pkg_name_only (already built-in).."
        continue
      fi

      # if we are intending to install the pkg
      if [ "$NO_INSTALL" = false -a "$FORCE" = false ];then
        # skip if package is already installed, unless --force given
        if [ "$FORCE" = false -a "`is_installed_pkg $pkg_name`" = true ];then
          echo -e "Package ${magenta}${pkg_name_only}${endcolour} already installed."
          echo -e "Use the -f option to force installation: $SELF -f -g $pkg_name_only"
          continue
        fi
      fi
      
      # get deps early (if any)
      list_deps "$pkg_name" > ${TMPDIR}/${pkg_name}_dep_list &

      # DOWNLOAD PKG
      pkg_download "$pkg_name"

      [ ! -f "$PKGFILE" ] && PKGFILE="`find "$CURDIR" -maxdepth 1 -type f -name "${pkg_name}.*${pkg_ext}"`"
      # try grabbing $CURDIR/pkgname.pkg_ext
      [ ! -f "$PKGFILE" ] && PKGFILE="`find "$CURDIR" -maxdepth 1 -type f -name "${pkg_name}*.${pkg_ext}"`"
      # now try grabbing $CURDIR/pkgname.*
      [ ! -f "$PKGFILE" ] && PKGFILE="`find "$CURDIR" -maxdepth 1 -type f -name "${pkg_name}.*"`"
      # maybe try $CURDIR/pkgname-*.*
      [ ! -f "$PKGFILE" ] && PKGFILE="`find "$CURDIR" -maxdepth 1 -type f -name "${pkg_name}-*.*"`"
      # maybe try $CURDIR/pkgname_*.*
      [ ! -f "$PKGFILE" ] && PKGFILE="`find "$CURDIR" -maxdepth 1 -type f -name "${pkg_name}_*.*"`"
      # maybe try $CURDIR/pkgname*.*
      [ ! -f "$PKGFILE" ] && PKGFILE="`find "$CURDIR" -maxdepth 1 -type f -name "${pkg_name}*.*"`"

      # add extension if Pkg returned an erroneous or user dir
      [ -d "$PKGFILE" ] && PKGFILE="${PKGFILE}.$pkg_ext"
      
      # if we found the package to install in CURDIR
      if [ -f "${PKGFILE}" ];then
        
        # check if we install or not
        if [ "${NO_INSTALL}" = false ];then

          # if a valid pkg, with files to extract
          if [ "`pkg_contents "$PKGFILE" 2>/dev/null`" != '' ];then
            #INSTALL PKG
            [ "`is_local_pkg "$PKGFILE"`" = true ] && pkg_install "${PKGFILE}"
          fi
          
        fi
        
        # if pkg was installed, or Pkg is simply downloading all deps
        if [ "`is_installed_pkg "$pkg_name_only"`" = true -o "${NO_INSTALL}" = true ];then 
          
          # get the dependencies for this package
          get_deps "${pkg_name}"
          
        fi

      else # PKGFILE not a file
        echo "Can't find ${PKGNAME} or not a valid pkg.."
      fi

    else # no matches in repo found
      echo "Cannot find ${PKGNAME}.."
    fi
    
    # done with this pkg, add it to done list, will be skipped it seen again, until loop is finished
    echo "$pkg_name_only" >> $TMPDIR/PKGSDONE
  done
}


choose_pkg(){                    # choose from a list of matching packages FUNCLIST
  

  # exit if no valid options
  [ ! "$1" -o "$1" = "" -o "$1" = "-" ] && print_usage get && exit 1
  
  # get $REPONAME and $EX 
  . ${PKGRC}
  
  local REPOEX    # extension of pkgs in the current repo $REPONAME (from rc file)
  local PKGEX     # pkg extension we get from $1, defaults to $REPOEXT is empty
  local PKGNAME   # the name of the pkg, we get this from $1
  local PKGNAME_ONLY  # the pkg name without version, we get this from PKGNAME
  local PKGS      # the list of PKGS returned matching $1/$PKGNAME
  local INT=1     # used to provide numbered lists
  
  REPOEX=$EX
  # get pkg extension
  PKGEX=`get_pkg_ext "$1"`
  
  # if no extension, set to extension of current repo
  [ "$PKGEX" = '' ] && PKGEX=$REPOEX
  
  # get pkg name with version, no extension or path
  PKGNAME="$(basename "$1" .$PKGEX)"
  
  # get the full pkg name, to compare against repo pkgs we find
  PKGNAME_FULL="`get_pkg_name "$PKGNAME"`"
  
  # get pkg name only .. without version or suffix
  PKGNAME_ONLY=`get_pkg_name_only "$PKGNAME"`

  # remove any previous user choice lists
  rm $TMPDIR/PKGLIST &>/dev/null
  rm $TMPDIR/USRPKGLIST &>/dev/null
  
  # get all pkgs that match the given pkgname 
  # returns full pkg names (field1 of repo, pkgname with ver but no extension) each on a new line
  PKGS="`$PKGSEARCH "${PKGNAME}"`"
  
  if [ "$FORCE" = false -a "`is_installed_pkg "$PKGNAME_FULL"`" = true -a "$HIDE_INSTALLED" = true ];then
    # remove it from choices
    PKGS="`echo "$PKGS" | grep -v ^$PKGNAME_FULL\$`"
  fi
  
  # extra steps for ubuntu and debian repos, if multiple choices returned.. remove non-compatible archs, remove dev and dbg pkgs... 
  if [ "$PKGEX" = "deb" -a "`echo "$PKGS" | wc -l`" != "1" ];then

    ARCH="`uname -m`"
    #remove x64 pkgs from choices if not using an x64 cpu
    [ "$ARCH" != "x86_64" ] && PKG="`echo "$PKGS" | grep -v -E 'amd64|x86_64'`"
    
    # set any pkgs matching current arch to top of list
    for LINE in `echo "$PKGS"  | sort -r` #first pkg found (newest) added to top, then the next, etc, sort use sort -r to keep newest at top of new list
    do
      # if not searching for -dev or -dgb pkg, move it to bottom of the list
      if [ "`echo "$PKGNAME" | grep -E "\-dbg_|\-dev_"`" = "" -a "`echo "$LINE" | grep -E "\-dbg_|\-dev_"`" != "" ];then
        PKGS="`echo "$PKGS" | grep -v  "$LINE"`" 
        PKGS="$PKGS
$LINE"
      fi
      # if pkg is for current cpu arch, move it to top of the list
      if [ "`echo "$LINE" | grep -m1 "$ARCH"`" != "" ];then
        PKGS="`echo "$PKGS" | grep -v  "$LINE"`" 
        PKGS="$LINE
$PKGS"
      fi
    done
    #remove debug and dev pkgs
    #PKGS="`echo "$PKGS" | grep -v "\-dbg_"`"
    #PKGS="`echo "$PKGS" | grep -v "\-dev_"`"
  fi

  # get the user to choose which packages they want to install
  if [ "$ASK" = true -a "$PKGS" != "" ];then
    echo "Please choose the package number. For the first package,"
    echo "enter '1', without quotes. To install multiple packages,"
    echo "enter the numbers, separated by a comma. Example:  1,3,4"
    echo
  fi

  # if using ubuntu/debian packages, put pkg_* before pkg-* .. else dont
  [ "$PKGEX" = 'deb' ] && sort='sort -r' || sort='sort'
  
  # go through each actual pkg that matches the pkgname search, make it a numbered list
  echo "$PKGS" | $sort | while read LINE
  do
    if [ "$LINE" != "" -a "$LINE" != "," -a "$LINE" != " " ];then
      [ "$ASK" = true ] && echo "${INT}. $LINE"
      echo "${INT}. $LINE" >> $TMPDIR/PKGLIST
      INT=$(($INT + 1))
    fi
  done
  
  # if pkg list was made
  if [ -f $TMPDIR/PKGLIST -a "`cat $TMPDIR/PKGLIST 2>/dev/null`" != "" ];then
    
    # set to first pkg only as default
    if [ "$ASK" = false ];then
      USRPKGLIST="$(echo "$PKGS" | $sort | head -1)" 
      echo "$USRPKGLIST" > $TMPDIR/USRPKGLIST
    fi
    
    # user can now input which actual pkgs to get, chosen by number
    if [ "$ASK" = true ];then
      echo 
      echo "Give the numbers of the packages you want to install,"
      echo -n "separated by a comma, or hit ENTER only to skip: "
      read USRPKGLIST1 </dev/tty
      
      # if user chose nothing (hit ENTER only), just skip
      [ "$USRPKGLIST1" = '' ] && continue
      
      # split the results into newlines, create the list of chosen pkgs (used by other funcs)
      echo "${USRPKGLIST1}" | tr ',' '\n' | while read LINE
      do
        # set chosen pkg choice(s)
        echo "`grep "^$LINE. " "$TMPDIR/PKGLIST" 2>/dev/null | cut -f2 -d' '`" >> $TMPDIR/USRPKGLIST
      done
    fi

    # remove temp file.. but keep $TMPDIR/USRPKGLIST, it contains our users choices, and is used by pkg_get() and get_deps()
    rm $TMPDIR/PKGLIST &>/dev/null
  fi
}


pkg_combine(){                   # combine a pkg and deps into one single pkg FUNCLIST
  
  # exit if no valid options
  [ ! "$1" -o "$1" = "-" ] && print_usage pkg-combine && exit 1
  
  . ${PKGRC}
  
  local EX=''
  local PKGNAME=''
  local PKGNAME_ONLY=''
  local PKG_FILENAME=''
  local PKG_FILE=''
  local ALL_DEPS=''
  local PKG_DEPLIST=''
  local SUFFIX=${CP_SUFFIX}
  local BUILD_DIR=$TMPDIR/build_pkg
  local SFS_FILE
  local please_wait=false
  local PREVDIR="$CURDIR"
  local ask_opt=$ASK
  local force_opt=$FORCE
  
  cd "$WORKDIR"
  
  # get pkg extension
  EX=`get_pkg_ext "$1"`
  
  # get reliable package names
  PKGNAME="$(basename "$1" .$EX)"
  PKGNAME=`get_pkg_name "$PKGNAME"`
  PKGNAME_ONLY=`get_pkg_name_only "$PKGNAME"`
  
  PKG_FILE="${WORKDIR}/${PKGNAME}.$EX" #the file to install

  # we want to include all deps, except builtins, by default
  # we dont set HIDE_BUILTINS here, we leave that up to user
  # when user gives -F, HIDE_BUILTINS= false, and builtin 
  # pkgs will be included in the package created
  export FORCE=true
  export HIDE_USER_PKGS=false
  
  # get full pkg filename (inc name-ver.ext).. try repos first
  PKG_FILENAME="`cut -f8 -d'|' ${HOME}/.packages/Packages-* | grep -m1 "^$PKGNAME"`"
  # then WORKDIR if needed (dont include the combined pkgs)
  [ "$PKG_FILENAME" = "" ] && PKG_FILENAME="`ls -1 "$WORKDIR" | grep -v "${SUFFIX}" | grep -v ".sfs\$" | grep -m1 "^$PKGNAME"`"
  
  # just in case its empty, revert back to the earlier PKGNAME value
  [ "$PKG_FILENAME" = "" ] && PKG_FILENAME="$PKGNAME" 
  
  [ "$PKG_FILENAME" = "" ] && error "Cant find $1" && exit 1
  
  # update PKGFILE with new pkg filename (PKG)
  PKG_FILE="${WORKDIR}/${PKG_FILENAME}" 
  
  # check if the desired file has already been built
  [ "$COMBINE2SFS" = true ] && final_ext=sfs || final_ext=pet
  [ -f "${WORKDIR}/${PKGNAME}-${SUFFIX}.$final_ext" ] && echo -e "File ${magenta}${WORKDIR}/${PKGNAME}-${SUFFIX}.${final_ext}${endcolour} already exists." && continue

  # get list of deps for PKGNAME, if no deps, exit
  PKG_DEPLIST="`FORCE=$force_opt list_deps $PKGNAME_ONLY`"
  [ "$PKG_DEPLIST" = "" ] && echo "No need to combine, $PKGNAME has no dependencies." && exit 1

  # if exact match of pkgname is found in a repo list
  if [ "`is_repo_pkg "$PKGNAME"`" = true ];then
    
    echo "Please wait.. Gathering dependency information."
    
    # get the deps of the pkg, but dont install
    FORCE=$force_opt find_deps "$PKGNAME"
    ALL_DEPS="`cat $TMPDIR/deps_installed $TMPDIR/deps_missing 2>/dev/null | sort | uniq`"
    
    if [ ! -f "$PKG_FILE" -o "$FORCE" = true ];then
      ASK=false pkg_download "$PKGNAME"
    fi
      
    # make work dirs
    mkdir -p "$BUILD_DIR/"
    mkdir -p "$BUILD_DIR/${PKGNAME}-${SUFFIX}"
    
    # copy the main pkg to the tmp dir
    cp "$PKG_FILE" "$BUILD_DIR/" 2>/dev/null || error "Could not add the main package '$PKGNAME_ONLY'"
    
    # make a cleaned list to go over (sanity check)
    ALL_DEPS_LIST="`echo "$ALL_DEPS" | tr ',' '\n' | grep -v "^\$" | sort | uniq`"

    # go through each dep listed
    echo "$ALL_DEPS_LIST" | while read LINE  
    do
      
      [ "$LINE" = "" -o "$LINE" = "-" -o "$LINE" = " " -o "$LINE" = "," -o "$LINE" = ", " ] && continue 
      
      # only include builtins if HIDE_BUILTINS=true
      [ "`is_builtin_pkg "$LINE"`" = true -a "$HIDE_BUILTINS" = true ] && continue
      
      # only include devx pkgs if user gave the -f option
      [ "`is_devx_pkg "$LINE"`" = true -a "$force_opt" = false ] && continue
      
      # find the matching package(s)
      [ "`list_downloaded_pkgs "$LINE"`" = "" ] && ASK=false pkg_download "$LINE"
      
      # get the downloaded file
      PKGDEP="`find "$WORKDIR" -maxdepth 1 -type f -name "${LINE}*" | grep -v ".sfs\$" | grep -v "${SUFFIX}" | head -1`"
      
      # if we didn't get it, try other repos
      if [ ! -f "$PKGDEP" ];then
        PKGREPO=''; PKGREPO="`LANG=C which_repo $LINE | cut -f2 -d' ' | head -1`"
        [ "$PKGREPO" != "" ] && ASK=false pkg_download "$LINE"
      fi  
      
      #if downloaded
      if [ -f "$PKGDEP" -o "$FORCE" = true ];then
        
        # copy dep to the tmp dir, with the main pkg
        [ ! -f "$BUILD_DIR/$PKGDEP" ] && cp "$PKGDEP" "$BUILD_DIR/$(basename $PKGDEP)" || error "Cannot copy $PKGDEP to $BUILD_DIR/$(basename $PKGDEP)" 
      
      else # dep not found, may be missing, or in another repo
        echo -e "${yellow}Warning:${endcolour} $LINE not downloaded to $WORKDIR.. Cannot add $LINE.."
        continue
      fi
    done

    # we should now be ready to make our combined pkg
    cd "$BUILD_DIR/${PKGNAME}-${SUFFIX}"
    
    PARENTPKG=${PKGNAME}
    
    # for all pkgs in the tmp dir (nto including any 'combined' pkgs)
    TMP_PKGS="`find "$BUILD_DIR/" -maxdepth 1 -type f -name "*" | grep -v $SUFFIX | grep -v ^$ | grep -v ' ' | sort | uniq`"
    
    for i in $TMP_PKGS
    do
      
      # skip if not a valid pkg file
      [ ! "$i" -o "$i" = ' ' -o "$i" = '' -o ! -f "$i" ] && continue
      
      # dont include the combined pkgs 
      [ "`echo "$i" | grep -m1 "${SUFFIX}"`" != "" ] && continue
      
      # get the extensions of each file .. they might be from different repos, so cant use $EX
      base="`basename "$i" 2>/dev/null`"
      FILE_EXT=`get_pkg_ext "$base"`
      
      [ ! "$base" -o "$base" = ' ' -o "$base" = '' ] && continue

      # get name without version for this pkg ($i)
      name_only=`get_pkg_name_only "$i"`
      
      [ ! "$name_only" -o "$name_only" = ' ' -o "$name_only" = '' ] && continue

      CONFIRM=y
      if [ "$ask_opt" = true ];then
        echo -n "Add package: $name_only  ($FILE_EXT)  (y/N):  "
        read -n 1 CONFIRM </dev/tty
        echo
      else 
        echo "Adding package: $name_only  ($FILE_EXT)"
      fi

      # skip pkg if user wants to skip it
      if [ "$CONFIRM" != 'y' ];then
        rm "$i"
        continue
      fi

      # add each file
      case $FILE_EXT in
      pet) 

        # get pet type
        file -b "${i}" | grep -i -q "^xz" && TAREXT=xz || TAREXT=gz
        [ "$TAREXT" = 'xz' ] && taropts='-xJf' || taropts='-zxf'
        TARFILE="${i/.pet/.tar.$TAREXT}"
        # convert and extract
        pet2tgz "${i}" 1>/dev/null
        # untar the tar file
        tar $taropts "$TARFILE" -C "$BUILD_DIR/" 2>/dev/null
        sync
        rm -f "$TARFILE" 2>/dev/null # remove the file created by pet2tgz
        # copy extracted contents (only the stuff inside the extracted folders)
        cp -a --preserve=all -f -r "${i/.pet/}/"* "$BUILD_DIR/${PARENTPKG}-${SUFFIX}/"
        # now remove the pet
        rm "${i}"
        # remove the folder 
        rm -rf "${i/.$FILE_EXT/}/"
        sync
        ;;

      deb) 

        #cp "$i" "$BUILD_DIR/${PARENTPKG}-${SUFFIX}"
        undeb "$i" 2>$TMPDIR/$SELF-cp-errlog
        rm "$i"
        ;;

      *tgz|*txz|*tar.gz|*tar.xz|*xz|*gz)

        #cp "$i" "$BUILD_DIR/${PARENTPKG}-${SUFFIX}"
        file -b "${i}" | grep -i -q "^xz" && TAREXT=xz || TAREXT=gz
        [ "$TAREXT" = 'xz' ] && taropts='-xJf' || taropts='-zxf'
        
        # if pkg contains a dir called $PKGNAME as the root dir (instead of just ./),
        if [ "`tar -tf "$i" | grep "^$name_only"`" != '' ];then
          
          # then extract tar contents to $BUILD_DIR/ ..
          # ..and we will get $BUILD_DIR/$PKGNAME/
          tar $taropts "$i" -C "$BUILD_DIR/"  1>/dev/null
          
          # now copy $BUILD_DIR/$PKGNAME/* into our output (combined pkg) dir
          cp -a --preserve=all -f -r "$BUILD_DIR/${name_only}/"* "$BUILD_DIR/${PARENTPKG}-${SUFFIX}"
          
          # remove the folder we just extracted
          rm -rf "${name_only}/${PARENTPKG}-${SUFFIX}"
        
        else # pkg contents start with ./

          tar $taropts "$i" 1>/dev/null
          rm "$i"
        
        fi
        
        ;;
      
      rpm)
          echo "RPM packages not yet supported"
          continue
        ;;

      esac
    done
    
    # now we are ready to build our combined pkg
    cd "$BUILD_DIR/"
    
    # if not building SFS, build a .pet
    if [ "$COMBINE2SFS" = false ];then #240613
      echo "Building PET package.. Please wait.."

      # build pet package... start with $removing PKGNAME-${SUFFIX}.pet.specs
      rm ${PKGNAME}-${SUFFIX}/*.specs 2>/dev/null
      
      # get compression type
      file -b "${PKGNAME}-${SUFFIX}" | grep -i -q "^xz" && TAREXT=xz || TAREXT=gz

      # tar up the folder
      tar -c -f ${PKGNAME}-${SUFFIX}.tar ${PKGNAME}-${SUFFIX} &>/dev/null
      sync

      case $TAREXT in
        xz)xz -z -9 -e ${PKGNAME}-${SUFFIX}.tar ;;
        gz)gzip --best ${PKGNAME}-${SUFFIX}.tar ;;
      esac

      TARBALL="${PKGNAME}-${SUFFIX}.tar.$TAREXT"
      FULLSIZE="`stat --format=%s ${TARBALL}`"
      MD5SUM="`md5sum $TARBALL | cut -f 1 -d ' '`"
      echo -n "$MD5SUM" >> $TARBALL
      sync

      mv -f $TARBALL ${PKGNAME}-${SUFFIX}.pet
      sync
      
      if [ $? -eq 1 ];then
        echo "Cannot create PET file ${PKGNAME}-${SUFFIX} from dir."
        error "Please check `pwd`"
      fi
      
      # move our new PET to $WORKDIR
      mv ${PKGNAME}-${SUFFIX}.pet $WORKDIR/${PKGNAME}-${SUFFIX}.pet
      # get the size
      s=`LANG=C du -m "$WORKDIR/${PKGNAME}-${SUFFIX}.pet" | sed "s/\s.*//"`
      
    else #240613  build a .sfs
      echo "Building SFS package.. Please wait.."
      
      dir2sfs "${PKGNAME}-${SUFFIX}" 1>/dev/null
      
      # get the full file name, it may (or not) have been appended with '-DISTRO_VERSION'
      SFS_FILE=`find . -maxdepth 1 -type f -name "*${PKGNAME}-${SUFFIX}*.sfs"`

      s=`LANG=C du -m "${SFS_FILE}" | sed "s/\s.*//"`
      MD5SUM=`md5sum "$SFS_FILE" | cut -f1 -d ' '`
      mv "$SFS_FILE" "$WORKDIR/"
    fi

    # done, go back to work dir from WORKDIR/build_pkg
    cd "$WORKDIR"
    rm -R  "$BUILD_DIR/" 2>/dev/null
    
    # create install command
    if [ "$COMBINE2SFS" = false ];then
      PKGEXT=pet
      PKGCMD="Install command: $SELF -i ${PKGNAME}-${SUFFIX}"
    else
      PKGEXT=sfs
      PKGCMD="Install command: sfs_installer ${WORKDIR}/${PKGNAME}-${SUFFIX}.sfs"
    fi

    #226013 updated output
    echo -e "Created package ${magenta}${PKGNAME}-${SUFFIX}.${PKGEXT}${endcolour} (${s}MB)"
    echo "The md5 checksum: $MD5SUM"
    echo "$PKGCMD"
      
  else # no exact PKGNAME match in repo
    not_found "${PKGNAME}"
    exit 1
  fi
  
  cd "$PREVDIR"
}


pkg_update(){                    # update installed pets, if updates exist in repo FUNCLIST
  
  # exit if no valid options
  [ ! "$1" -o "$1" = "-" ] && print_usage pkg-update && exit 1
  
  # get rc file settings
  . ${PKGRC}
  
  local PKGNAME=''
  local PKGLIST=''
  local BUILTINS=''
  
  PKGNAME=$(basename "$1")
  
  PKGNAME=`get_pkg_name "$1"`
  PKGNAME_ONLY=`get_pkg_name_only "$1"`
  
  # get installed packages
  PKGLIST="`list_installed_pkgs "$PKGNAME_ONLY"`"

  is_builtin=`is_builtin_pkg "$PKGNAME"`
  
  # dont update builtins unless -F was given 
  if [ "$is_builtin" = true -a "$HIDE_BUILTINS" = true ];then
    echo -e "Package ${magenta}${PKGNAME}${endcolour} is built in, not updating."
    #echo -e "Use `$SELF -F --pkg-update $PKGNAME` to update it anyway."
    exit 0
  fi
  
  # iterate over the list
  echo "$PKGLIST"  | grep -v ^$ | sort | uniq | while read LINE; do

    [ ! "$LINE" -o "$LINE" = '' ] && continue
    
    # if this pkg ($LINE) is not from a known repo, we cant compare its version to anything else, skip it
    [ "`is_repo_pkg "$LINE"`" = false ] && echo -e "Package ${magenta}$LINE${endcolour} not found in any repos." && continue
    
    PNAME='' PKGVER='' LATEST_PKG='' LATEST_PKGVER='' ASKREPLY='y'
    # get pkg name (without version) and version of current PKG
    
    PNAME=`get_pkg_name_only "$LINE"`
    PKGVER="`LANG=C echo "$LINE" | sed -e 's/^[^0-9]*-//g' | cut -f1 -d'_' | cut -f1 -d'-'`"
    
    # get latest versions
    LATEST_PKG="`list_all_pkg_names "${PNAME}" | grep -m1 "^${PNAME}"`"
    LATEST_PKGVER="`LANG=C echo "$LATEST_PKG" | sed -e 's/^[^0-9]*-//g' | cut -f1 -d'_' | cut -f1 -d'-'`"
    
    # check pkg version against installed version
    if [ "$LATEST_PKGVER" != "" -a "$PKGVER" != "" ];then
      vercmp $LATEST_PKGVER gt $PKGVER 2>/dev/null
      RESULT=$?
      if [ "$RESULT" = 0 ];then #newer version available
        
        if [ "$ASK" = true ];then
          echo "Do you want to update to ${PNAME}-${LATEST_PKGVER}? [y/N]   "
          read -n 1 ASKREPLY </dev/tty
          [ "$ASK" = true ] && echo -ne "\b\b\n"
        fi
        
        if [ "$ASK" = false -o "$ASKREPLY" = "y" ];then
          echo "Updating $PNAME to $LATEST_PKGVER"
          #150813 dont involve deps, support --ask and --force
          ASK=$ASK FORCE=$FORCE pkg_download "$LATEST_PKG"
          # get the full name of the file we downloaded
          PKGFILE="`list_downloaded_pkgs "$LATEST_PKG"`"
          # now install it
          [ "`is_local_pkg`" = true ] && ASK=$ASK FORCE=$FORCE pkg_install "$PKGFILE"
        fi 
      
      else #280613 inform user if no update found
        echo "$PNAME-$PKGVER (installed) is the latest available."
      fi #end if vercmp XX gt YY = 0
    
    else #280613
      error "Package versions could not be compared: 
${LATEST_PKGVER:-unknown latest}, ${PKGVER:-unknown installed version}"
      exit 1
    fi #end if PKGVER != ""
  done
}


clean_pkgs(){                    # delete downloaded pkg files of installed pkgs FUNCLIST
  local pkg_to_rm
  [ "$ASK" = true ] && ASKOPT='--ask'
  # list all (matching) installed pkgs
  list_installed_pkgs | while read line; 
  do 
    # get all pkgs except the combined (user-created) pkgs
    pkg_to_rm="`list_downloaded_pkgs $line | grep -v $CP_SUFFIX`"
    # if it has a downloaded pkg in $WORKDIR, (offer to) delete it
    [ "$pkg_to_rm" != '' ] && rm -v "${WORKDIR}/$pkg_to_rm";
  done
}


# dependency funcs
get_deps_entry(){
  [ "$1" = '' -o "$1" = "-" ] && print_usage list-deps && exit 1
  
  # get current $REPOFILE, $DEPSEARCH
  #. ${PKGRC}
  
  local PKGNAME="$1"
  local pkg_ext=''
  local repo_files=''
  local deps_list=''
  local deps=''
  local repo_of_pkg=''
  local repo_file_of_pkg=''
  
  # get pkg extension
  pkg_ext=`get_pkg_ext "$1"`

  
  # get repo file to search from RC file
  repo_file_of_pkg="$REPOFILE"
  
  # if searching dependencies in all repos
  if [ "$DEPSEARCH" = "list_all_pkg_names" ];then
  
    # get the repo that $PKGNAME lives in
    repo_of_pkg=`which_repo "$PKGNAME" | cut -f2 -d' ' | head -1`
    # then get the repo file for that repo.. that is where this pkg lists its deps
    repo_file_of_pkg=`grep -m1 ^"$repo_of_pkg" ~/.pkg/sources-all | cut -f3 -d'|'`
  
  fi
  
  # add the full path to the repo file
  repo_file_of_pkg="$HOME/.packages/$repo_file_of_pkg"
    
  # search for deps entry in repo file.. look for |pkgname.ext|
  deps_list="`LANG=C grep -m1 "|${PKGNAME}.$pkg_ext|" $repo_file_of_pkg 2>/dev/null | cut -f9 -d'|' | grep '+' | sed -e "s/:any//g" -e "s/&[geql][eqt][0-9a-z._-]*//g" | grep -vE '/ge|/le'`"

  # try again if needed.. look for ^pkgname|
  [ "$deps_list" = "" -a "$PKGNAME" != '' ] && deps_list="`LANG=C grep -m1 "^${PKGNAME}|" $repo_file_of_pkg 2>/dev/null | cut -f9 -d'|' | grep '+' | sed -e "s/:any//g" -e "s/&[geql][eqt][0-9a-z._-]*//g" | grep -v '/ge'`"

  # try again if needed.. look for |pkgname|
  [ "$deps_list" = "" -a "$PKGNAME" != '' ] && deps_list="`LANG=C grep -m1 "|${PKGNAME}|" $repo_file_of_pkg 2>/dev/null | cut -f9 -d'|' | grep '+' | sed -e "s/:any//g" -e "s/&[geql][eqt][0-9a-z._-]*//g" | grep -vE '/ge|/le'`"

  # try again, look for dep-*
  [ "$deps_list" = "" -a "$PKGNAME" != '' ] && deps_list="`LANG=C grep -m1 "^${PKGNAME}-" $repo_file_of_pkg 2>/dev/null | cut -f9 -d'|' | grep '+' | sed -e "s/:any//g" -e "s/&[geql][eqt][0-9a-z._-]*//g" | grep -vE '/ge|/le'`"

  # try again if needed.. with underscore.. dep_*
  [ "$deps_list" = "" -a "$PKGNAME" != '' ] && deps_list="`LANG=C grep -m1 "^${PKGNAME}_" $repo_file_of_pkg 2>/dev/null | cut -f9 -d'|' | grep '+' | sed -e "s/:any//g" -e "s/&[geql][eqt][0-9a-z._-]*//g" | grep -vE '/ge|/le'`"

  # if no deps, exit with error
  [ "$deps_list" != "" ] && echo "$deps_list"
}


list_all_installed_pkgs(){
  # reset list of installed pkgs
  echo -n '' > $TMPDIR/installed_pkgs

  if [ "${HIDE_INSTALLED}" = true -a "$FORCE" = false ];then
    # add user installed pkgs to list of pkgs to remove from final output
    cut -f2 -d'|' $HOME/.packages/user-installed-packages >> $TMPDIR/installed_pkgs
  fi
  
  if [ "${HIDE_BUILTINS}" = true ];then
    # add builtins to list of pkgs to remove from final output
    cut -f2 -d'|' $HOME/.packages/woof-installed-packages >> $TMPDIR/installed_pkgs
  fi
  
  if [ -f $HOME/.packages/devx-installed-packages ];then
    # add devx pkgs to list of pkgs to remove from final output
    cut -f2 -d'|' $HOME/.packages/devx-installed-packages >> $TMPDIR/installed_pkgs
  fi
  
  if [ -f $HOME/.packages/layers-installed-packages ];then
    # add layers list of pkgs to remove from final output
    cut -f2 -d'|' $HOME/.packages/layers-installed-packages >> $TMPDIR/installed_pkgs
  fi
  
  if [ -f $TMPDIR/installed_pkgs -a ! -z $TMPDIR/installed_pkgs ];then
    sort -u $TMPDIR/installed_pkgs | grep -v ^$ > $TMPDIR/installed_pkgs__sorted
    mv $TMPDIR/installed_pkgs__sorted $TMPDIR/installed_pkgs
  fi
}


has_deps(){                      # return true if $1 has deps, else false
  [ "$1" = '' -o "$1" = "-" -o ! "$1" ] && echo false
  [ "`get_deps_entry $1`" != '' ] && echo true || echo false
}


list_deps(){                     # list all deps of PKG, space separated on one line FUNCLIST
  [ "$1" = '' -o "$1" = "-" ] && print_usage list-deps && exit 1
  
  echo true > /tmp/pkg/list_deps_busy
  
  # get current $REPOFILE, $DEPSEARCH
  #. ${PKGRC}
  
  local PKGNAME=''
  local PKGNAME_ONLY=''
  local pkg_ext=''
  local repo_files=''
  local deps_list=''
  local deps=''
  local repo_of_pkg=''
  local repo_file_of_pkg=''
  
  # get pkg extension
  pkg_ext=`get_pkg_ext "$1"`
  
  #pkg name only ,no path, no extension
  PKGNAME="$(LANG=C basename "$1" .$pkg_ext)" 
  PKGNAME=`get_pkg_name "$PKGNAME"`
  PKGNAME_ONLY=`get_pkg_name_only "$PKGNAME"`

  # create list of installed pkgs ($TMPDIR/installed_pkgs) for later
  list_all_installed_pkgs &
  
  # get the deps of the pkg, note, in the repo deps are NOT listed by proper pkg names, .. they are +dbus,+glib,+SDL
  
  # search for deps entry in repo file.. look for |pkgname.ext|
  deps_list="`LANG=C get_deps_entry "$PKGNAME"`"

  # if no deps, exit with error
  [ "$deps_list" = "" ] && rm /tmp/pkg/list_deps_busy 2>/dev/null && return 1
  
  # remove the '+' from the start of each dep
  deps="${deps_list/+/}" # remove first + at start of line
  deps="${deps//,+/ }"   # remove others .. DEPS will now be just 'dep1 dep2 dep3'  
  deps="${deps//  / }"   # remove double spaces
  
  if [ "$deps" != '' -a "$deps" != ' ' ];then

    # put all deps of pkg in a tmp file
    echo "$deps" | tr ' ' '\n' | tr ',' '\n' | sort -u > $TMPDIR/all_deps_0

    # remove any deps in installed pkgs list from all deps.. to leave only missing deps
    comm -23 ${TMPDIR}all_deps_0 ${TMPDIR}installed_pkgs | sort -u | grep -v ^$ > ${TMPDIR}all_deps_1

    rm -f ${TMPDIR}DEP_DONE 2>/dev/null
    
    if [ -f $TMPDIR/all_deps_1 -a ! -z $TMPDIR/all_deps_1 ];then
      # recursive search deps of deps
      for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
      do
        deps_list_file="${TMPDIR}all_deps_${i}"
        
        if [ -f $deps_list_file ];then
          next_deps_list_file="${TMPDIR}all_deps_$(($i + 1))"
          # for each dep in $deps, get their deps too
          for subdep in `cat $deps_list_file | sort -u | uniq | grep -v ^$`
          do
            local subdeps_entry=''
            local subdeps=''
            local subdeps_list=''

            [ "$subdep" = '' -o "$subdep" = ' ' ] && continue

            subdep="`get_pkg_name_only $subdep`"
            
            local already_done=`grep -m1 "^${subdep}\$" ${TMPDIR}DEP_DONE 2>/dev/null`
            [ "$already_done" != '' ] && continue

            local is_builtin=`is_builtin_pkg "$subdep"`
            local is_in_devx=`is_devx_pkg "$subdep"`

            [ "$HIDE_BUILTINS" = true -a "$is_builtin" = true ] && continue 
            [ "$HIDE_BUILTINS" = true -a "$is_in_devx" = true ] && continue 

            subdeps_entry="`get_deps_entry "$subdep"`"
            subdeps="${subdeps_entry/+/}" # remove first + at start of line
            subdeps="${subdeps//,+/ }"    # remove others .. DEPS will now be just 'dep1 dep2 dep3' 
            subdeps="${subdeps//  / }"    # remove double spaces

            if [ "$subdeps" != '' ];then
              # remove everything after the + (if the + is followed by alphanumeric chars), then add to tmp files
              subdeps_list="`echo "${subdeps}" | tr ' ' '\n' | grep -v ^$ | sed -e 's/++/+++/g' -e 's/+[a-z0-9].*//g'`"
              echo "$subdeps_list" >> ${TMPDIR}DEP_DONE
              echo "$subdeps_list" >> $next_deps_list_file
            fi
          done
          rm -f ${TMPDIR}DEP_DONE 2>/dev/null
        fi
      done
      rm -f ${TMPDIR}DEP_DONE 2>/dev/null
  
      # add all deps together, sorted, duplicated removed
      sort -u ${TMPDIR}all_deps_* | grep -v ^$ > ${TMPDIR}all_deps_sorted
      mv ${TMPDIR}all_deps_sorted ${TMPDIR}all_deps
    
    fi
    
  fi

  # remove any deps in installed pkgs list from all deps.. to leave only missing deps
  if [ -f ${TMPDIR}installed_pkgs -a ! -z  ${TMPDIR}installed_pkgs ];then
    comm -23 ${TMPDIR}all_deps ${TMPDIR}installed_pkgs | sort -u | grep -v ^$ > ${TMPDIR}missing_deps
  fi

  [ ! -f ${TMPDIR}missing_deps -o -z ${TMPDIR}missing_deps ] && rm /tmp/pkg/list_deps_busy 2>/dev/null && return 1
  
  [ ! -f ${TMPDIR}missing_deps ] && return 1

  # get fixed deps list
  deps="`LANG=C cat ${TMPDIR}missing_deps 2>/dev/null | tr ' ' '\n' | while read dep
  do
    echo $(get_pkg_name_only "$dep")
  done | sort -u | tr '\n' ' '`"

  [ "$deps" != "" ] && echo "$deps"
  
  # clean up
  rm ${TMPDIR}missing_dep* ${TMPDIR}installed_pkg* ${TMPDIR}all_dep* ${TMPDIR}DEP_DONE /tmp/pkg/list_deps_busy 2>/dev/null
}


find_deps(){                     # make 2 lists: DEPS_INSTALLED and DEPS_MISSING FUNCLIST
  
  # This function takes 1 argument: PKGNAME
  #
  # PKGNAME should be the name of a package in one of your repos, 
  # such as 'vlc' or 'hardinfo'.
  #
  # This function creates 2 files: $TMPDIR/deps_missing and $TMPDIR/deps_installed.
  # Each file is list the dependencies for PKGNAME, each dependency on a new line.
  # get_deps() can then go through those files and download/install the missing deps.
  #
  # If --force was given, all deps will be treated as missing.
  
  # get current repo ($REPOFILE) 
  . ${PKGRC}
  
  local PKGNAME=''            # the pkg given ($1), may be full name, or generic name (no version), etc
  local PKGNAME_ONLY=''       # the pkg given ($1), without version (vlc,htop,etc)
  local pkg_ext=''            # the pkg extension, blank if not a valid extension or none given
  local repo_files=''         # the list of repo files to check, may be current only or all
  local deps_list=''          # deps of PKGNAME in comma-delimited format: dep1,dep2,dep3
  local deps_on_new_lines=''  # as above, but each dep on a new line
  local deps_missing=''       # comma separated list of missing deps
  local deps_installed=''     # comma separated list of deps already installed
  local dep=''                # dep name scraped from deps_list, usually the same as dep_name_only
  local dep_match=''          # used to find matches in the repo for $dep
  local dep_name_only=''      # short (generic) pkg name, no version (vlc,htop,etc)
  local dep_full_name=''      # pkg name with version (vlc-2.3.3-i686_s700, etc)
  local loading_indicator     # blank if only a few deps to parse, or .
  
  # get pkg extension
  pkg_ext=`get_pkg_ext "$1"`
  
  # pkg name with version, but no path, no extension
  PKGNAME="$(basename "$1" .$pkg_ext)"

  # we can't rely on the user input, try to get the right pkg names
  PKGNAME=`get_pkg_name "$PKGNAME"`       # vlc -> 'vlc-2.3-blah_etc
  PKGNAME_ONLY=`get_pkg_name_only "$PKGNAME"`   # vlc-2.3-blah_etc -> vlc
  
  # if PKGNAME still empty, we cant find its deps, move on
  [ -z "$PKGNAME" ] && return 1
  
  # didn't exit yet, so remove the old tmp dirs
  rm $TMPDIR/deps_installed &>/dev/null
  rm $TMPDIR/deps_missing   &>/dev/null
  rm $TMPDIR/deps_missing1  &>/dev/null

  # loop through all repo files, or current repo only, depending on PKGSEARCH in RC file
  # add the full path to the file(s) while we are getting the list of repo files
  [ "$DEPSEARCH" = "list_all_pkg_names" ] && repo_files="`list_sources_files | sed -e "s|^|$HOME/.packages/|g" | tr '\n' ' '`" || repo_files="$HOME/.packages/$REPOFILE"
  
  # get the list of deps from the repo entry of this pkg
  deps_list="`LANG=C list_deps "$PKGNAME"`"
  
  # remove builtins from list unless HIDE_BUILTINS=false
  if [ "${HIDE_BUILTINS}" = true ];then
    echo "$deps_list" | tr ' ' '\n'  | grep -v ^$ > ${TMPDIR}all_deps
    # add woof pkgs to list of pkgs to remove from final output
    cut -f2 -d'|' $HOME/.packages/woof-installed-packages | grep -v ^$ | sort | uniq >> $TMPDIR/installed_pkgs
    # remove any deps in installed pkgs list from all deps.. to leave only missing deps
        
    sort -u ${TMPDIR}all_deps > ${TMPDIR}all_deps_sorted
    mv ${TMPDIR}all_deps_sorted ${TMPDIR}all_deps
    
    sort -u ${TMPDIR}installed_pkgs > ${TMPDIR}installed_pkgs_sorted
    mv ${TMPDIR}installed_pkgs_sorted ${TMPDIR}installed_pkgs
    
    comm -23 ${TMPDIR}all_deps ${TMPDIR}installed_pkgs | grep -v ^$ > ${TMPDIR}missing_deps
    deps_list="`cat "${TMPDIR}missing_deps" | grep -v ^$ | sort | tr '\n' ' ' `"
  fi

  # so now, $deps_list='dep1 dep2 dep3'
  
  # now get the deps list with each dep on its own line
  deps_on_new_lines="`echo "$deps_list" | tr ' ' '\n'`"
  
  # exit if no deps to parse
  [ "$deps_on_new_lines" = '' ] && return 1
  
  # set a loading bar (appending dots....) if we have numerous deps to search
  [ `echo "$deps_on_new_lines" | wc -l` -gt 4 ] && loading_indicator='.' || loading_indicator=''
  
  # now.. we go through ALL deps listed, and create a list for installed or not .. $dep will be 'gtkdialog3', for example
  echo "$deps_on_new_lines" | grep -v ^$ | while read dep
  do
    # append dots as we go, like a loading spinner
    [ "$loading_indicator" = '.' ] && echo -n "$loading_indicator"

    # $dep is currently
    dep_full_name=`get_pkg_name "$dep"`     #vlc-2.3.3-i586_s700
    dep_name_only=`get_pkg_name_only "$dep"`  #vlc
    
    # skip these non pkgs
    [ "`is_repo_pkg "$dep_name_only"`" = false ] && continue
    
    # if we added this dep to the list of PKGs already done, skip it
    [ "`grep -m1 "^$dep_name_only\$" $TMPDIR/PKGSDONE 2>/dev/null`" != '' ] && continue
    
    # lets check if the $dep is installed or not
    
    # if dep was found in a repo and not installed, add to missing deps list
    if [ "$FORCE"  = true -o "`is_installed_pkg "$dep_full_name"`" = false ];then
      grep -m1 "^$dep_name_only\$" $TMPDIR/deps_missing 2>/dev/null || echo "$dep_name_only" | grep -v "^$PKGNAME" >> $TMPDIR/deps_missing

    else
      # else if the dep is already installed, add to installed deps list
      grep -m1 "^$dep_name_only\$" $TMPDIR/deps_installed 2>/dev/null || echo "$dep_name_only" | grep -v "^$PKGNAME" >> $TMPDIR/deps_installed
    fi

    # clean up deps_installed, remove duplicates, etc
    if [ -f $TMPDIR/deps_installed ];then
      cat $TMPDIR/deps_installed 2>/dev/null| sort | uniq >> $TMPDIR/deps_installed1
      [ -f $TMPDIR/deps_installed1 ] && mv $TMPDIR/deps_installed1 $TMPDIR/deps_installed 2>/dev/null
    fi

  done # end of while $dep

  # make a comma separated list from newlines
  deps_installed="`cat $TMPDIR/deps_installed 2>/dev/null | sort | uniq | tr '\n' ',' | sed -e 's/,,/,/' -e 's/,$//' -e 's/^,//'`"
  deps_missing="`cat $TMPDIR/deps_missing 2>/dev/null | sort | uniq | tr '\n' ',' | sed -e 's/,,/,/' -e 's/,$//' -e 's/^,//'`"

  #120213, fixed, force all deps to be in the download list, if --force was given
  if [ "$FORCE" = true ];then
    # dont skip installed deps (except builtins.. handled elsewhere)
    if [ "$deps_installed" != "" ];then
      deps_missing="${deps_installed},${deps_missing}"
      deps_missing="`echo "${deps_missing//,,/}" | sed -e 's/,$//' -e 's/^,//'`"
    fi
  fi

  # later, get_deps() will use $DEPS_MISSING and $DEPS_INSTALLED
  DEPS_MISSING="$deps_missing"
  DEPS_INSTALLED="$deps_installed"
  # so export for other funcs to use
  export DEPS_MISSING
  export DEPS_INSTALLED
  
  # end appending dots... msg, by printing a new line
  [ "$loading_indicator" != '' ] && echo 

}


get_deps(){                      # find, get and install the deps of pkg FUNCLIST

  [ -z "$1" -o ! "$1" -o "$1" = "-" ] && print_usage deps && exit 1
  
  . ${PKGRC} #150813
  
  local EX
  local PKGNAME
  local DEPCONFIRM
  
  # get pkg extension
  local EX=`get_pkg_ext "$1"`
  
  # get pkg name with version, but no path, no extension
  local PKGNAME="$(LANG=C basename "$1" .$EX)" 
  
  # don't rely on user input, get the name w version from repos
  local PKGNAME=`get_pkg_name "$PKGNAME" 2>/dev/null`
  local PKGNAME_ONLY=`get_pkg_name_only "$PKGNAME" 2>/dev/null`
  
  local pkg_is_builtin=`is_builtin_pkg "$PKGNAME_ONLY" 2>/dev/null`
  local pkg_already_done=`LANG=C grep -m1 "^$PKGNAME_ONLY\$" $TMPDIR/PKGSDONE 2>/dev/null`

  # if pkg is builtin, skip it, we dont need to get its dependencies
  [ "$pkg_is_builtin" = true -a "$HIDE_BUILTINS" = true ] && continue

  # skip if already processed, it should be listed in $TMPDIR/PKGSDONE
  [ "$pkg_already_done" != "" -a "$FORCE" = false ] && continue 

  echo -n "Resolving dependencies.." # find deps will append ... as it goes

  # wait until list_deps() is finished (if it's running at all...)
  while [ -f /tmp/pkg/list_deps_busy ];do
    echo -n '.' 
    sleep 0.75
  done

  echo
  
  # if list_deps() created a file listing the deps, get it from the file created, else, run list deps to be sure
  [ -f ${TMPDIR}/${pkg_name}_dep_list ] && DEPS_MISSING="`cat ${TMPDIR}/${pkg_name}_dep_list 2>/dev/null`" || DEPS_MISSING="`list_deps "$PKGNAME" 2>/dev/null`"
  
  # if we have missing deps, or are downloading them all regardless (INSTALLDEPS=false), or using --force
  if [ "$DEPS_MISSING" != "" -o "${NO_INSTALL}" = true -o "$FORCE" = true ];then 
    
    # ask to download (and maybe install) the deps
    DEPCONFIRM=y
    if [ "$ASK" = true ];then
      echo "Missing deps: $DEPS_MISSING"
      echo -n "Download the missing dependencies$QTAG:  "
      read -n 1 DEPCONFIRM </dev/tty
      echo
      # skip if user chose --ask and didn't answer 'y'
      [ "$DEPCONFIRM" != "y" ] && return
    fi

    # if user answered yes, we will now download (and maybe install) the deps
    if [ "$DEPCONFIRM" = "y" -o "$FORCE" = true ];then
      # make a list of the deps, each on a new line for each dep/newline
      WARNLIBS=''; SEP='';
      
      # if more than one missing dep, set separator to a comma
      [ ! -z "$DEPS_MISSING" -a "`echo "$DEPS_MISSING" | wc -l`" != "1" -a "`echo "$DEPS_MISSING" | wc -l`" != "0" ] && SEP=','
    
      # clean up our deps list, and make space separated only (no commas)
      DEPS_MISSING="`LANG=C echo "${DEPS_MISSING//,/ }" | grep -v '^,' | grep -v "^\$"`"

      # show deps info, if any available
      [ "${DEPS_MISSING}" != ""  ]   && echo "Dependencies to get: ${DEPS_MISSING//,/, }"
      [ "$FORCE" = false -a "${DEPS_INSTALLED}" != "" ] && echo "Dependencies installed: `LANG=C grep -v "^\$" $TMPDIR/deps_installed 2>/dev/null | head -1`"
      
      # for each missing dep  (or simply for each dep, if $FORCE is true)
      for DEP in $DEPS_MISSING
      do
        
        [ "$DEP" = "" -o "$DEP" = "${PKGNAME_ONLY}" -o "$DEP" = "${PKGNAME}" ] && continue #skip if the dep is the main package
        
        local DEPNAME=`get_pkg_name "$DEP" 2>/dev/null`
        local DEPNAME_ONLY=`get_pkg_name_only "$DEPNAME" 2>/dev/null`
        local DEPFILE=''
  
        # skip if already processed, it should be listed in $TMPDIR/PKGSDONE
        local dep_already_done=`LANG=C grep -m1 "^$DEPNAME_ONLY\$" $TMPDIR/PKGSDONE 2>/dev/null`
        [ "$dep_already_done" != "" -a "$FORCE" = false ] && continue 
        
        local dep_is_builtin=`is_builtin_pkg "$DEPNAME_ONLY" 2>/dev/null`
        local dep_is_usr_pkg=`is_usr_pkg "$DEPNAME_ONLY" 2>/dev/null`
        local dep_is_in_devx=`is_devx_pkg "$DEPNAME_ONLY" 2>/dev/null`

        # skip getting pkg if its a builtin, unless HIDE_BUILTINS=false
        if [ "$dep_is_builtin" = true -a "${HIDE_BUILTINS}" = true ];then
          echo "Skipping $DEPNAME_ONLY (already built-in).."
          continue
        fi

        # skip getting pkg if its user installed and not using --force
        if [ "$dep_is_usr_pkg" = true -a "${FORCE}" != true ];then
          echo "Skipping $DEPNAME_ONLY (already installed).."
          continue
        fi

        # skip getting pkg if its in the devx, unless HIDE_BUILTINS=false
        if [ "$dep_is_in_devx" = true -a "${HIDE_BUILTINS}" = true ];then
          echo "Skipping $DEPNAME_ONLY (already built-in).."
          continue
        fi

        #DOWNLOAD THE PKG
        pkg_download "$DEPNAME" 2>/dev/null

        # skip install unless NO_INSTALL=true
        if [ "${NO_INSTALL}" = false ];then
        
          # get the actual file we just downloaded to WORKDIR
          DEPFILE="`find "$WORKDIR" -maxdepth 1 -type f -name "$DEPNAME*" 2>/dev/null`"

          #INSTALL THE DEP, if it was downloaded
          [ "`is_local_pkg "$DEPFILE" 2>/dev/null`" = true ] && pkg_install "$DEPFILE" 2>/dev/null
          
          # mark the pkg as done!
          echo "$DEPNAME_ONLY" >> $TMPDIR/PKGSDONE

        else # if not installing, 
          # skip dep checking of the deps that dont get installed
          continue
        fi


        # we finished with this dep, mark it done,
        # .. so we can skip it if it appears again (in a recursive dep check loop for example)
        echo "$DEPNAME_ONLY" >> $TMPDIR/PKGSDONE #260713
        
        
      done #done for DEP in DEPS_MISSING
      
    fi #endif DEPCONFIM=y

  else 
    echo "No missing dependencies."
  fi # endif DEPS_MISSING != ''

  # if some deps were missing (listed but not found), print msg
  [ "$INSTALLDEPS" = true ] && actioned=installed || actioned=downloaded
  [ "$WARNLIBS" != "" ]     && echo -e "${yellow}Warning:${endcolour} Not $actioned from repo: $WARNLIBS"
  #exit 0 #110913
}


pkg_ldd_msg(){                   # prints final dep check msg FUNCLIST
  
  # exit if no valid usage
  [ ! "$1" -o "$1" = "-" ] && print_usage deps-check && exit 1 
  
  . ${PKGRC}
  
  local PKGNAME
  local FNDFILES
  local LIST
  local RES
  local MISSING
  
  # get pkg name
  PKGNAME=`get_pkg_name "$1"`
  rm $TMPDIR/pkg-$PKGNAME-MISSING.txt &>/dev/null
  
  [ "`is_installed_pkg "$PKGNAME"`" = false ] && print_usage deps-check && exit 1 
  
  # get the *.files for this pkg
  FNDFILES="`find $HOME/.packages/ -iname "${PKGNAME}.files" 2>/dev/null`"
  [ ! -f "$FNDFILES" ] && exit 1
  
  # get list of ldd-able file
  cat "$FNDFILES" | grep -E '/lib/|/bin/' | sort -u > ${TMPDIR}ldd_file_list
  [ -z ${TMPDIR}ldd_file_list ] && exit 0
  
  echo "Searching for missing dependencies.. Please wait."
  
  #loop through list
  for line in `cat ${TMPDIR}ldd_file_list`
  do
    [ ! -x "$line" ] && continue 
    RES="`ldd $line 2>/dev/null`"
    MISSING="`echo "$RES" | grep found`"
    [ "$MISSING" != "" -a "$MISSING" != " " ] && echo "  $line:
$MISSING" >> $TMPDIR/pkg-$PKGNAME-MISSING.txt
  done

  #print message
  if [ -f $TMPDIR/pkg-$PKGNAME-MISSING.txt ];then
    echo -e "${yellow}WARNING:${endcolour} The following files are missing the listed dependencies: "
    echo -e "`cat $TMPDIR/pkg-$PKGNAME-MISSING.txt | sort | uniq`\n"
  else
    echo -e "${green}OK:${endcolour} $PKGNAME has with no missing dependencies."
  fi
  rm -f ${TMPDIR}ldd_file_list 2>/dev/null
}


get_all_deps(){                  # try to install all missing deps FUNCLIST
 echo "Checking $(list_installed_pkgs | wc -l) installed packages for missing dependencies. Please wait..."
 rm $TMPDIR/pkg_get_all_deps 2>/dev/null
 
 list_installed_pkgs | while read LINE; do 
  DEPLIST="`LANG=C list_deps "$LINE"`"
  [ "$DEPLIST" != "" -a "$LINE" != "" ] && echo "$LINE|$DEPLIST" >> $TMPDIR/pkg_get_all_deps
 done
 
 [ ! -f $TMPDIR/pkg_get_all_deps ]   && echo "No missing dependencies." && exit 0
 ASKOPT='';   [ "$ASK" = true ]   && ASKOPT='--ask ';
 FORCEOPT=''; [ "$FORCE" = true ] && FORCEOPT='--force ';
 
 cat $TMPDIR/pkg_get_all_deps 2>/dev/null | while read LINE
 do
  [ "$LINE" = "" -o "`echo "$LINE" | grep -v '|'`" = "" ] && continue 
  # get pkg gname from field 1
  PKGNAME="${LINE%%|*}"
  DEPS="${LINE##*|}"
  
  echo "Checking $PKGNAME..."

  for DEP in $DEPS;
  do
    # try to get the pkg name
    DEPPKG="`list_all_pkg_names $DEP- | head -1`" || \
    DEPPKG="`list_all_pkg_names $DEP_ | head -1`" || \
    DEPPKG="`list_all_pkg_names $DEP  | head -1`"
    # if dep not in any repos, skip it
    [ "$DEPPKG" = "" ] && continue
    # skip if the dep is already installed
    [ "`is_installed_pkg $DEPPKG`" = true ] && continue
    # ask to get dep
    echo -n "Get the missing package: ${DEPPKG}$QTAG:  "
    echo
    [ "$ASK" = true ] && read -n 1 CONFIRM </dev/tty || CONFIRM=y
    [ "$ASK" = true ] && echo -ne "\b\b\n"
    # if user answered yes, we will now download the pkgs
    if [ "$CONFIRM" = "y" ];then
      NO_INSTALL=false pkg_get "$DEPPKG" # get the missing dep (and its deps)
    fi
  done
 done
 rm -f $TMPDIR/pkg_get_all_deps 2>/dev/null
}


list_dependents(){               # list user installed pkgs that depend on $1 FUNCLIST

  local PKGNAME=''
  local PKGNAME_ONLY=''

  if [ "$1" = '' ];then
    print_usage what-needs
    exit 1
  fi

  # try to get correct pkg names
  PKGNAME=`get_pkg_name "$1"`
  PKGNAME_ONLY=`get_pkg_name_only "$1"`
  
  # if pkg is not installed, then nothing depends on it
  if [ "`is_installed_pkg "$PKGNAME"`" = false ];then
    echo "Package $1 not installed, nothing depends on it."
    exit 1
  fi

  # list all pkgs (from all repos) with $PKGNAME_ONLY as a dep
  cut -f1,2,9 -d'|' $HOME/.packages/Packages-* \
    | sed -e "s/:any//g" -e "s/&[geql][eqt][0-9a-z._-]*//g" 2>/dev/null \
    | grep -E "+${PKGNAME_ONLY},|+${PKGNAME_ONLY}\|" 2>/dev/null \
    | cut -f2 -d'|' 2>/dev/null \
    | grep -v "^\$" \
    | grep -v "^#" \
    | grep -v "^$PKGNAME_ONLY\$" \
    | sort -u \
    >> ${TMPDIR}/dependents_list

  if [ "$HIDE_BUILTINS" = false ];then
    # list all builtin and devx packages with $PKGNAME_ONLY as a dependency.. 
    cut -f1,2,9 -d'|' $HOME/.packages/woof-installed-packages  $HOME/.packages/devx-installed-packages\
      $HOME/.packages/devx-only-installed-packages \
      | grep -E "+${PKGNAME_ONLY},|+${PKGNAME_ONLY}\|" \
      | cut -f2 -d'|' \
      | grep -v "^\$" \
      | grep -v "^#" \
      | grep -v "^$PKGNAME_ONLY\$" \
      | sort -u \
      >> ${TMPDIR}/dependents_list
  fi

  # remove duplicates
  sort -u ${TMPDIR}/dependents_list > ${TMPDIR}/dependents_list__sorted
  mv ${TMPDIR}/dependents_list__sorted ${TMPDIR}/dependents_list_tmp
  rm ${TMPDIR}/dependents_list

  # only keep the user installed pkgs in the list
  for pkg in `list_installed_pkgs | grep -v ^$PKGNAME`
  do
    [ "`grep -m1 "^$(get_pkg_name_only $pkg)\$" ${TMPDIR}/dependents_list_tmp`" != '' ] && echo "$pkg" >> ${TMPDIR}/dependents_list
  done
  
  # print the list if we have one
  [ -f ${TMPDIR}/dependents_list -a ! -z ${TMPDIR}/dependents_list ] && cat ${TMPDIR}/dependents_list
  rm ${TMPDIR}/dependents_lis* 2>/dev/null
}


# file conversion

deb2pet(){                       # $1 must be valid deb file or repo pkg FUNCLIST
  [ ! -f "$1" ] && print_usage deb2pet && exit 1
  
  local DEB="${CURDIR}/$(basename "${1}")" 
  local DIRNAME="${CURDIR}"
  #create file name we work with
  [ -f "$1" ] && DEB="$1" && DIRNAME="`dirname "$1"`"
  
  #keep old file, download it if needed
  #[ -f "$(basename "$1" .deb)" ] || ASK=$ASK FORCE=$FORCE pkg_download "$(basename "$1" .deb)"
  
  # if the deb exists
  if [ -e "$DEB" ]; then 
    for i in "$DEB" # for each deb given
    do
      #remove the extensions
      #example, will be something like FOLDR=$HOME/Desktop/atari800_3.1.0-2+b2_i386
      FOLDR="$(echo "$i"|sed 's/\.deb$//')"
    done
    
    #make the new dir, copy the deb file into it, and ci into it
    mkdir -p "$FOLDR"; cp "$DEB" "$FOLDR"; cd "$FOLDR"; 
    
    #get the new full path and filename
    DEB="`ls | grep ".deb"`"
    
    # extract into current dir and remov ethe copied deb file
    pkg_unpack "$DEB" 1>/dev/null
    
    #this will be something like  PKGNAME=atari800_3.1.0-2+b2_i386
    PKGNAME="`basename "$DEB" .deb`"
    
    #now we package up the stuff into a pet
    [ -d "${FOLDR}/$PKGNAME" ] && dir2pet "${FOLDR}/$PKGNAME" || dir2pet "$PKGNAME"

    [ ! -f "$FOLDR.pet" -a ! -f "${CURDIR}/${PKGNAME}.pet" ] && error "$FOLDR.deb NOT converted to PET package!"
    
    #clean up
    rm -rf "$FOLDR"

  else
    echo "Package '$(basename $DEB)' not found in '$CURDIR'."
    return 1
  fi
}


dir2pet(){                       # dir to PET, $1 must be valid dir FUNCLIST
  
  # exit if no options
  [ ! -d "$1" ] && print_usage dir2pet && exit 1
  
  DIR="$1"
  SUFFIX=''
  
  [ "$2" != "" ] && SUFFIX="$2"
  
  #[ -d "$DIR" ] && cd `dirname "$DIR"`

  # get pkg name only, 
  DIR="$(basename "${DIR}")" 
  [ "$SUFFIX" != "" ] && cp -R "$DIR" "${DIR}${SUFFIX}" && DIR="${DIR}${SUFFIX}" 
  
  echo "Converting directory '$DIR' to a .pet package."
  
  # we must have a dir with same name as a valid pkg 
  if [ -d "$DIR" ];then 
    # move it to the build dir, to work on
    mkdir -p "$CURDIR/build_pkg/"
    [ ! -e "$CURDIR/build_pkg/$DIR" ] && cp -R "$DIR" "$CURDIR/build_pkg/"

    #...borrowed from dir2pet script
    #w482 directory may already have a pet.specs, reuse it...
    NAMEONLY=""
    PUPMENUDESCR=""
    PUPOFFICIALDEPS=""
    PUPCATEGORY=""
    PUPPATH="" #100201
    ARCHDEPENDENT="yes" #100201
    DEFREPO="" #100201
    if [ -f $CURDIR/build_pkg/${DIR}/pet.specs ];then #160803
     #new: pkgname|nameonly|version|pkgrelease|category|size|path|fullfilename|dependencies|description|
     #optionally on the end: compileddistro|compiledrelease|repo| (fields 11,12,13)
     PETSPECS="`cat $CURDIR/build_pkg/${DIR}/pet.specs | head -n 1`" #160803
     while IFS="|" read -r F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 <&3
     do
       DB_pkgname="$F1"
       DB_nameonly="$F2"
       NAMEONLY="$DB_nameonly"
       DB_version="$F3"
       DB_pkgrelease="$F4"
       DB_category="$F5"
       PUPCATEGORY="$DB_category"
       DB_size="$F6"
       DB_path="$F7"
       PUPPATH="$DB_path" #100201
       DB_fullfilename="$F8"
       DB_dependencies="$F9"
       PUPOFFICIALDEPS="$DB_dependencies"
       DB_description="$F10"
       PUPMENUDESCR="$DB_description"
       DB_compileddistro="$F11"
       DB_compiledrelease="$F12"
       ARCHDEPENDENT="${DB_compileddistro}|${DB_compiledrelease}"
       DB_repo="$F13"
       DEFREPO="$DB_repo"
      done 3< $CURDIR/build_pkg/${DIR}/pet.specs
    fi

    # build .pet.specs

    BASEPKG="`basename $DIR`"
    DIRPKG="`dirname $DIR`"
    [ "$DIRPKG" = "/" ] && DIRPKG=""
    
    #difficult task, separate package name from version part...
    #not perfect, some start with non-numeric version info...
    [ "$NAMEONLY" = "" ] && NAMEONLY=`get_pkg_name_only "$BASEPKG"`

    # get pet details from the pre-existing pet.specs (if any): deps, category, descr, version, nameonly, arch, distro version
    PUPOFFICIALDEPS="$DB_dependencies"
    
    TOPCAT="$PUPCATEGORY"
    [ -z "$TOPCAT" ] && TOPCAT=BuildingBlock
    
    PUPMENUDESCR="$DB_description"
    [ -z "${PUPMENUDESCR}" ] && PUPMENUDESCR="No description provided"
    
    xPATTERN="s%${NAMEONLY}%%"
    VERSION="`echo -n "$BASEPKG" | sed -e "$xPATTERN" -e 's%^\\-%%'`"
    
    ARCHINDEPENDENT='yes'
    for ONEEXEC in `find $CURDIR/build_pkg/${DIR}/ -maxdepth 6 -type f -perm -o+x`
    do
      [ -f $ONEEXEC ] && [ "`file $ONEEXEC | grep ' ELF '`" != "" ] && ARCHINDEPENDENT='no'
    done
    
    # if it's a _DEV pkg.. it can't be ARCHINDEPENDENT
    case "${BASEPKG}" in *"_DEV"*) ARCHINDEPENDENT='no' ;; esac
    [ "`find $CURDIR/build_pkg/${DIR}/ -maxdepth 6 -type f -name '*.a' -o -type f -name 'lib*.so*' -o -type f -name '*.la'`" != "" ] && ARCHINDEPENDENT='no'
    [ "$ARCHINDEPENDENT" = "no" ] && COMPAT=$DISTRO_BINARY_COMPAT V=$DISTRO_COMPAT_VERSION

    # build pet spec
    echo "$BASEPKG|${NAMEONLY}|$VERSION|$DB_pkgrelease|$TOPCAT|$DB_size|$REPO_SUBDIR|${BASEPKG}.pet|$PUPOFFICIALDEPS|$PUPMENUDESCR|$COMPAT|$V||" > $CURDIR/build_pkg/${DIR}/pet.specs
    
    # delete the slackware package management files
    #if [ -d "$CURDIR/build_pkg/install" ];then 
    # rm -r "$CURDIR/build_pkg/install"; rmdir "$CURDIR/build_pkg/install";
    #fi

    # delete arch pkg stuff
    #rm -r "$CURDIR/build_pkg/.INSTALL" &>/dev/null
    #rm "$CURDIR/build_pkg/.PKGINFO" &>/dev/null

    # now tar up the folder, ready to make into tar.gz, then into .pet
    cd $CURDIR/build_pkg/

    # we need to choose xz or gzip pets
    arch=`uname -m`
    if [ "${arch:0:3}" = "arm" ];then
      TAREXT="gz"
    else 
      TAREXT="xz"
    fi

    # if in a pre-woof puppy then we dont use xz
    if [ ! -f ${HOME}/.packages/woof-installed-packages -o ! -f ${HOME}/.packages/woof-installed-packages ];then
      # pre woof format
      echo "PETMENUDESCR='${DIR}'" >  $CURDIR/build_pkg/${DIR}/${DIR}.pet.specs
      echo "PETOFFICIALDEPS=''"    >> $CURDIR/build_pkg/${DIR}/${DIR}.pet.specs
      echo "PETREGISTER='yes'"     >> $CURDIR/build_pkg/${DIR}/${DIR}.pet.specs
      compression=xz
      TAREXT="xz"
    fi
    tar -c -f ${DIR}.tar ${DIR} 1>/dev/null
    sync
    [ "`which xz`" = "" ] && TAREXT=gz
    case $TAREXT in
      xz)xz -z -9 -e ${DIR}.tar ;;
      gz)gzip --best ${DIR}.tar ;;
    esac

    # now get info needed to make a pet file
    TARBALL="${DIR}.tar.$TAREXT"
    FULLSIZE="`stat --format=%s ${TARBALL}`"
    MD5SUM="`md5sum $TARBALL | cut -f 1 -d ' '`"

    # add the info to the file
    echo -n "$MD5SUM" >> $TARBALL
    sync

    # now rename it to .pet
    mv -f $TARBALL ${DIR}.pet
    sync

    # move the created pet out of build_pkg, into WORK_DIR
    mv ${DIR}.pet $CURDIR/${DIR}.pet
    cd $CURDIR

    # clean up
    rm -f -R $CURDIR/build_pkg/
    echo -e "Package ${magenta}${DIR}.pet${endcolour} created."
    echo "The md5sum is: `md5sum ${DIR}.pet | cut -f1 -d' '`."
  else
    echo "Directory '$DIR' not found."
    exit 1
  fi
}


dir2sfs(){                       # $1 must be dir of pkg contents FUNCLIST
  
  if [ ! -d "$1" ];then
    print_usage dir2sfs
    exit 1
  fi
  
  # if found, we will append it to the SFS filename
  [ "$DISTRO_VERSION" != "" ] && SFS_SUFFIX="_${DISTRO_VERSION}" || SFS_SUFFIX=''
  
  # get sfs name only, no extension or path
  SFS_DIR="`basename "$1" .sfs`" 
  
  # if a valid dir
  if [ -d "$SFS_DIR" ];then
    rm "${SFS_DIR}/"*pet*specs 2>/dev/null #240613
    #start building the sfs file
    echo "Please wait... building SFS file.."
    LANG=C mksquashfs "$SFS_DIR" "${SFS_DIR}${SFS_SUFFIX}.sfs" -noappend &>/dev/null && SUCCESS="y" || SUCCESS=""
    if [ -z "$SUCCESS" -a ! -f "${SFS_DIR}${SFS_SUFFIX}.sfs" ]; then
      echo "Failed to create ${SFS_DIR}${SFS_SUFFIX}.sfs."
      exit 1
    fi
    chmod 644 "${SFS_DIR}${SFS_SUFFIX}.sfs" #shinobar
    sync
    #get size, and output msg
    s=`LANG=C du -m "${SFS_DIR}${SFS_SUFFIX}.sfs" | sed "s/\s.*//"`
    MD5SUM=`md5sum "${SFS_DIR}${SFS_SUFFIX}.sfs" | cut -f1 -d ' '`
    echo -e "Created ${magenta}${SFS_DIR}${SFS_SUFFIX}.sfs${endcolour} ( $s MB )"
    echo -e "The md5 checksum: $MD5SUM"
  else
    echo "Cannot create SFS:  '${SFS_DIR}' is not a directory."
    exit 1
  fi
  
  # clean up
  #rm -rf "${SFS_DIR}" &>/dev/null
  #rm -f "${SFS}${SFS_SUFFIX}"*.sfs-md5.txt &>/dev/null
  rm -f "${SFS}${SFS_SUFFIX}" &>/dev/null
}


dir2tgz(){                       # requires $1 as valid dir FUNCLIST
  
  [ ! -d "$1" ] && print_usage dir2tgz && exit 1
  
  DIR="${1/.t*gz/}"
  
  # remove trailing slash
  DIRNAME="`echo -n $DIR | sed -e 's%/$%%'`" 
  DIRNAME="`basename ${DIRNAME}`" # get name only, no path
  
  # make sure any pet specs are named correctly - this new tar file might later be converted to a .pet
  echo "`ls -1 ${DIRNAME} | grep 'pet.specs'`" | while read LINE
  do 
    mv "${DIRNAME}/$LINE" "${DIRNAME}/pet.specs" 2>/dev/null; 
  done
  
  # create the tar file
  ##echo "Adding directory to '${DIRNAME}.tar.gz'.."
  tar -c -f "${DIRNAME}.tar" "${DIRNAME}/"
  gzip "${DIRNAME}.tar"
  sync
  
  # print message
  if [ -f "${DIRNAME}.tar.gz" ];then
    echo -e "Package ${magenta}${DIRNAME}.tar.gz${endcolour} created."
    echo "The md5sum is: `md5sum ${DIRNAME}.tar.gz | cut -f1 -d' '`."
  else
    echo "Package '${DIRNAME}.tar.gz' NOT created."
    return 1
  fi
}


pet2sfs(){                       # convert pet to sfs, $1 must be file or repo pkg FUNCLIST
  
  # require valid option or quit
  [ ! -f "$1" ] && print_usage pet2sfs && exit 1
  
  pkg_ext=`get_pkg_ext "$1"`
  
  [ "$pkg_ext" != pet ] && print_usage pet2sfs && exit 1
  
  #110213,0.9.1 we want the file in $WORKDIR 
  #[ ! -f "${WORKDIR}/$(basename "$1" .pet).pet" ] && cp -f "${1/.pet/}.pet" "${WORKDIR}/$(basename "$1" .pet)" 2>/dev/null
  
  PKGNAME="$(basename "$1" .pet)" #get pkg name only, no extension or path
  PKGFILE="${CURDIR}/${PKGNAME}.pet" #the file to install
  
  # determine the compression, extend test to 'XZ'
  file -b "${PKGFILE}" | grep -i -q "^xz" && TAREXT=xz || TAREXT=gz
  [ "$TAREXT" = 'xz' ] && taropts='-xJf' || taropts='-zxf'

  pet2tgz "${PKGFILE}" 1>/dev/null
  
  # now extract the files into $CURDIR/$PKGNAME/
  tar $taropts "${PKGFILE//.pet/.tar.$TAREXT}" 2> $TMPDIR/$SELF-cp-errlog
            
  # if DISTRO_VERSION found, the sfs will prob have a suffix
  [ "$DISTRO_VERSION" != "" ] && SFS_SUFFIX="_${DISTRO_VERSION}" || SFS_SUFFIX=''
  
  # remove the old one, if needed
  rm "${PKGNAME}${SFS_SUFFIX}.sfs" 2>/dev/null
  
  # create the new one
  dir2sfs "${CURDIR}/${PKGNAME}" && rm -rf "${CURDIR}/${PKGNAME}"
  
  # remove the .tar.$TAREXT file
  rm -f "${PKGNAME}.tar.$TAREXT"
  
  # if pkg put the pet in $CURDIR (not user), remove it
  #[ -f "${PKGFILE}" -a "`dirname "$1"`" != "$CURDIR" ] && rm -f "${PKGFILE}" 2>/dev/null
  
  # print message
  if [ ! -f "${PKGNAME}.sfs" -a ! -f "${PKGNAME}${SFS_SUFFIX}.sfs" ];then
    echo "Package '${PKGNAME}.pet' not converted."
    return 1
  fi
}


pet2tgz(){                       # convert to tar.gz, $1 must be valid file FUNCLIST

  # if $1 is not a valid pkg name or a file that exists then exit.. 
  [ ! -f "$1" ] && print_usage pet2tgz && exit 1
  
  pkg_ext=`get_pkg_ext "$1"`
  [ "$pkg_ext" != "pet" ] && print_usage pet2tgz && exit 1
  
  PKGNAME="$(basename "$1" .pet)" # get pkg name only, no extension or path
  PKGFILE="$1"          # build the pkg file path

  # backup the package, to restore it later
  cp -f "$PKGFILE" "$TMPDIR/`basename $PKGFILE`.backup" 1>/dev/null
  
  chmod +w "$PKGFILE" # make it writable.
  FOOTERSIZE="32"

  # determine the compression, extend test to 'XZ'
  finfo=`file -b "$PKGFILE"`
  case $finfo in
    gz*|GZ*) EXT=gz ;;
    xz*|XZ*) EXT=xz ;;
    *) error "Unsupported compression type, or corrupted package." && exit 1 ;;
  esac
  
  # get the md5
  MD5SUM="`tail -c $FOOTERSIZE \"$PKGFILE\"`"
  NEWNAME="`echo -n \"$PKGFILE\" | sed -e "s/\\.pet$/\\.tar\\.$EXT/g"`" #131122
  head -c -$FOOTERSIZE "$PKGFILE" > $NEWNAME
  NEWMD5SUM="`md5sum \"$NEWNAME\" | cut -f 1 -d ' '`"
  sync
  [ ! "$MD5SUM" = "$NEWMD5SUM" ] && exit 1

  # restore original pet pkg
  [ -f "$TMPDIR/`basename $PKGFILE`.backup" ] && mv -f "$TMPDIR/`basename $PKGFILE`.backup" "$PKGFILE"

  # print message
  if [ -f "$NEWNAME" ];then
    echo -e "${green}Success${endcolour}: Package ${magenta}`basename ${NEWNAME}`${endcolour} created."
    echo "The md5sum is `md5sum "$NEWNAME" | cut -f1 -d' '`."
  else
    error "Package ${PKGNAME}.pet not converted!"
    return 1
  fi
}


pet2txz(){                       # calls pet2tgz FUNCLIST
  pet2tgz "$1"
}


sfs2pet(){                       # convert sfs to pet, requires $1 as a valid sfs FUNCLIST

  # exit if no valid options
  [ ! -f "$1" ] && print_usage sfs2pet && exit 1
  
  # exit if user did not give an SFS file, or didnt give a file at all
  [ "`file "$1" | grep  Squashfs`" = '' ] && print_usage sfs2pet && exit 1

  # we want the file in $CURDIR
  #[ ! -f "${WORKDIR}/$(basename "${1}")" ] && cp -f "$1" "${WORKDIR}/$(basename "${1}")" 2>/dev/null
  
  SFSNAME="$(basename "$1")"
  SFSEXT="${SFSNAME##*.}"
  
  # if DISTRO_VERSION found, the sfs will prob have a suffix
  [ "$DISTRO_VERSION" != "" ] && SFS_SUFFIX="_${DISTRO_VERSION}" || SFS_SUFFIX=''
  
  # create the name without path or extension (may include a $SUFFIX)
  ROOTNAME=`basename "$SFSNAME" ".$SFSEXT"`
  
  # build the file name we will work on
  SFS="${CURDIR}/${ROOTNAME}.$SFSEXT"
  
  if [ -f "$SFS" -a "$SFS" != "" ];then

    echo "Unsquashing $SFSNAME.. Please wait.."

    # remove any older dirs, and unsquash
    rm -rf "${CURDIR}/squashfs-root/"
    LANG=C unsquashfs "$SFS"  &>/dev/null
    
    # lets remove the SFS suffix, to get back the the 'valid' PET name
    ROOTNAME_NOSUFFIX=`echo "$ROOTNAME" | sed -e "s/$SFS_SUFFIX//"`

    # create the folder we will package up
    mv squashfs-root "${ROOTNAME_NOSUFFIX}/"

    dir2tgz "${ROOTNAME_NOSUFFIX}" 1>/dev/null

    tgz2pet "${ROOTNAME_NOSUFFIX}".tar.gz 1>/dev/null

    # remove the dir and the tgz we just created
    rm -rf "${ROOTNAME_NOSUFFIX}"
    rm -f "${ROOTNAME_NOSUFFIX}".tar.gz
    
    if [ -f "${ROOTNAME_NOSUFFIX}.pet" ];then
      echo -e "${green}Success${endcolour}: Package '${magenta}${ROOTNAME_NOSUFFIX}.pet${endcolour}' created."
      echo "The md5sum is: `md5sum ${ROOTNAME_NOSUFFIX}.pet | cut -f1 -d' '`"
    else
      echo "Package '${ROOTNAME_NOSUFFIX}.pet' not converted."
      return 1
    fi
  fi
}


tgz2pet(){                       # convert $1 (a tar.gz or tgz) to .pet FUNCLIST
  
  [ ! -f "$1" ] && print_usage tgz2pet TARFILE && exit 1
  sync
  TARBALL="$1"
  [ ! -f "$TARBALL" ] && echo "The archive '$TARBALL' could not be found." && exit 1

  cp -f $TARBALL "$TMPDIR/`basename $TARBALL`.backup" 1>/dev/null

  TARBALL="${CURDIR}/$(basename "${TARBALL}")"
  chmod 644 "$TARBALL" #make it writable.
  echo "Converting `basename ${TARBALL}`.."
  
  #only accept .tgz or .tar.gz .tar.xz files...
  EXT=''
  case ${TARBALL} in
    *.tar.gz) EXT='.tar.gz' ;;
    *.tgz)    EXT='.tgz' ;;
    *.tar.xz) EXT='.tar.xz' ;;
    *.txz)    EXT='.txz' ;;
    *) echo "${1##*/}: File extension not allowed" >&2 ; exit 1 ;;
  esac
  [ "$EXT" = "" ] && error "$TARBALL must be a .tgz, .tar.gz, .txz or .tar.xz file" && exit 1

  #split TARBALL path/filename into components...
  BASEPKG="`basename $TARBALL $EXT`"
  DIRPKG="$CURDIR"
  [ "$DIRPKG" = "/" ] && DIRPKG=""
  case $EXT in
  *gz)OPT=-z;;
  *xz)OPT=-J;;
  esac

  # move pkg, update extensions (tgz -> .tar.gz, txz -> .tar.xz)
  # make code later more readable
  case $EXT in
  *tgz)mv -f $TARBALL $DIRPKG/${BASEPKG}.tar.gz
   TARBALL="$DIRPKG/${BASEPKG}.tar.gz"
   EXT='.tar.gz';;
  *txz)mv -f $TARBALL $DIRPKG/${BASEPKG}.tar.xz
   TARBALL="$DIRPKG/${BASEPKG}.tar.xz"
   EXT='.tar.xz';;
  esac

  # if tarball expands direct to '/' want to wrap around it (slackware pkg)... 100628 add -z ...
  # man bad bug here... the thing isn't expanded! #131122
  if [ "`tar ${OPT} --list -f ${TARBALL} | head -n 1`" = "./" ];then
    tar --one-top-level=${BASEPKG} -xf ${TARBALL} 
    tar --remove-files -c -f ${DIRPKG}/${BASEPKG}.tar ${BASEPKG}/
    case $EXT in
    *gz) gzip --force --best ${DIRPKG}/${BASEPKG}.tar ;;
    *xz) xz --force -z -9 -e ${DIRPKG}/${BASEPKG}.tar ;;
    esac
  fi

  FULLSIZE="`stat --format=%s ${TARBALL}`"
  MD5SUM="`md5sum $TARBALL | cut -f 1 -d ' '`"
  echo -n "$MD5SUM" >> $TARBALL
  sync
  mv -f $TARBALL $DIRPKG/${BASEPKG}.pet
  sync
  
  # restore original tar file
  [ -f "$TMPDIR/`basename $TARBALL`.backup" ] && mv -f "$TMPDIR/`basename $TARBALL`.backup" "$TARBALL"

  # print msg
  if [ -f "${DIRPKG}/${BASEPKG}.pet" ];then
    echo -e "${green}Success:${endcolour} Created ${magenta}${BASEPKG}.pet${endcolour}."
    echo "This is the md5sum: `md5sum ${DIRPKG}/${BASEPKG}.pet | cut -f1 -d' '`"
  else
    error "Could not convert ${DIRPKG}/${BASEPKG}.$EXT"
    return 1
  fi
}


txz2pet(){                       # convert txz to pet, requires $1 as valid file FUNCLIST
  [ ! -f "$1" ] && print_usage txz2pet TARFILE && exit 1
  FILE="$1"   # full path, filename and extension
  #keep old file, download it if needed
  #[ -f "$(basename "$1" .txz)" ] || pkg_download "$(basename "$1" .txz)" #  200813 try to download it
  # we want $FILE in $CURDIR
  [ ! -f "${CURDIR}/$(basename "${FILE}")" ] && cp -f "$FILE" "${CURDIR}/$(basename "${FILE}")" 2>/dev/null
  FILE="${CURDIR}/$(basename "${FILE}")"
  #set vars
  FILENAME="`basename "$FILE"`" # filename and extension only
  BARENAME="${FILENAME/.t*xz/}" # filename, no extension.. 
  PETFILE="${CURDIR}/${BARENAME}.pet" # the full path and filename of the pet file
  PETNAME="`basename "$PETFILE"`" # the filename of the pet file
  # create the pet directory, if needed
  mkdir -p "${CURDIR}/${BARENAME}"
  [ ! -d "${CURDIR}/${BARENAME}" ] && { echo "PET directory not created or found."; exit 1; }
  # unpack the file
  [ -f "$FILENAME" ] && tar -Jxvf "$FILENAME" -C "${BARENAME}/" 1>/dev/null || echo "Cannot untar $FILENAME"
  # create the pet file
  dir2pet "$BARENAME" || echo "PET working directory not found"

  if [ -f "$PETFILE" ];then # if pet file was created
    # remove the pet file working directory
    rm -R "${CURDIR}/${BARENAME}/" 2>/dev/null
    rmdir "${CURDIR}/${BARENAME}/" 2>/dev/null
    # report the file was created #nope, no need, dir2pet will do it
    #echo "Package '$PETNAME' created successfully."
  else
    echo "Package "$PETFILE" file not created"
    return 1
  fi
  # delete the original txz file
  rm -f "$FILE" &>/dev/null
}


# other

menu_entry_msg(){                # show menu entry details of installed pkg FUNCLIST
  
  # exit if not valid usage
  [ ! "$1" -o "$1" = "-" ] && exit 1

  . ${PKGRC}

  local MENUFILE=''
  local pkg_file_list=''
  local no_display=''
  local terminal_only=''
  local pkg_command=''

  # get the menu file, if it exists
  pkg_file_list=`find ${HOME}/.packages/ -maxdepth 1 -type f -name "${1}*.files"`

  [ -f "$pkg_file_list" ] && MENUFILE="`LANG=C grep -m1 '/usr/share/applications/' "$pkg_file_list" | grep -i -m1 ".desktop\$"`" || return 1

  # if pkg has a .desktop file
   if [ -f "$MENUFILE" ];then

    # exit if the menu item is set to NoDisplay
    no_display="`grep -m1 ^NoDisplay=true "$MENUFILE" 2>/dev/null`"
    terminal_only="`grep -m1 ^Terminal=true "$MENUFILE" 2>/dev/null`"

    # fix menu entries
    sed -i 's/ %u//g' "$MENUFILE"
    sed -i 's/ %U//g' "$MENUFILE"
    sed -i 's/ %f//g' "$MENUFILE"
    sed -i 's/ %F//g' "$MENUFILE"
    sed -i 's/ %d//g' "$MENUFILE"
    sed -i 's/ %D//g' "$MENUFILE"
    
    update_menus &

    # get the details for a final msg
    MENU_CAT="`LANG=C grep -m1 "^Categories=" $MENUFILE 2>/dev/null | cut -f2 -d'=' | sed -e 's/\(.*\);/\1/g' -e 's/.*;//g' | head -1`"
    APATTERN="[ ,]${MENU_CAT}" #MHHP
    TOPMENU="`LANG=C grep -m1 "${APATTERN}" /etc/xdg/menus/hierarchy | cut -f1 -d' ' | head -1`"
    if [ "$TOPMENU" = "" ];then
      APATTERN="[ ,]${MENU_CAT};"
      TOPMENU="`LANG=C grep -m1 "${APATTERN}" /etc/xdg/menus/hierarchy | cut -f1 -d' ' | head -1`"
    fi
    MENU_NAME="`LANG=C grep -m1 "^Name=" $MENUFILE | cut -f2 -d'=' | head -1`"
    
    [ "$TOPMENU" = '' ] && TOPMENU="$MENU_CAT"
    
    # replace the Categories= line with one which has only the top, main category..
    # .. this should prevent duplicate menu entries
    #cat "$MENUFILE" | grep -v ^Categories > ${TMPDIR}fixed.desktop
    #echo "Categories=${TOPMENU};" >> ${TMPDIR}fixed.desktop
    #mv ${TMPDIR}fixed.desktop $MENUFILE

    # print msg
    if [ "$no_display" != "" -o "$terminal_only" != '' ];then
      pkg_command="`grep -m1 ^Exec= "$MENUFILE" | cut -f2 -d'='`"
      [ "$pkg_command" != '' ] && echo -e "To run, type:  ${bold}${pkg_command}${endcolour}"
    else 
      echo -e "Menu entry:     ${lightblue}${TOPMENU:-[None]}${endcolour} -> ${lightblue}${MENU_NAME:-[None]}${endcolour}"
    fi
    
    return 0
  fi
  return 1
}


update_menus() {                 # update menus, calls fixmenus, refreshes WM
  echo started > /tmp/pkg/update_menus_busy
  fixmenus &>/dev/null
  # refresh JWM menus if using JWM window manager
  [ "`which jwm`" != "" -a "`ps -e | grep jwm`" != "" ] && jwm -reload &>/dev/null
  rm /tmp/pkg/update_menus_busy 2>/dev/null
  return 0
}


check_net(){                     # check net connection (before downloading) FUNCLIST
  [ -f $TMPDIR/internetsuccess ] && echo 0 && exit 0 #220613
  [ ! "$1" -o "$1" = "-" ] && URL="8.8.8.8" || URL="`echo  ${1} | awk -F/ '{print $3}'`"
  LANG=C ping -4 -c1 -q "$URL" &>/dev/null #220613
  REPLY=$?
  [ $REPLY -eq 0 ] && echo -n "ok" > $TMPDIR/internetsuccess #220613
  echo 0
}


get_stdin(){                     # read from stdin (when - is last option) FUNCLIST
  read -t 0.1 STDINVAR
}


not_found(){                     # list alternative packages when no match in repos FUNCLIST
  PKGNAME="${1/.pet/}"
  #echo "$APPTITLE"
  #echo "Package '${PKGNAME}' not found in current repo..  "
  if [ "$(ls "${WORKDIR}/"| grep "${PKGNAME}")" != "" ];then
    [ "`list_downloaded_pkgs "${PKGNAME}"`" != "" ] && echo "These downloaded packages match your search: 
`list_downloaded_pkgs "${PKGNAME}"`"
  fi
    [ "`$PKGSEARCH "${PKGNAME}"`" != "" ] && echo "These packages in the repos match your search: 
`$PKGSEARCH "${PKGNAME}"`"
  return 1
}


first_run (){                    # welome message on first run
  
  # quit if not the first run
  [ ! -f ~/.pkg/firstrun ] && return 0
  # print msg
  echo '============================================================'
  echo -e "  ${bold}$APPNAME $APPVER${endcolour} - a command-line package manager"
  echo '============================================================'
  echo
  echo "  pkg repo-update      # update the contents of each installed repo"
  echo "  pkg repo-list        # list all available repos"
  echo "  pkg repo <name>      # change to the chosen repo"
  echo "  pkg show-config      # show current Pkg settings"
  echo "  pkg workdir <DIR>    # change where to keep downloaded packages"
  echo
  echo "  pkg search <term>    # search all fields in the current repo"
  echo "  pkg names <pkgname>  # search package names in the current repo"
  echo "  pkg status <pkgname> # print info about the given package"
  echo "  pkg get <pkgname>    # install & download packages and dependencies"
  echo
  echo " You can run the commands below to learn more about Pkg:"
  echo
  echo "  pkg examples         # show lots more example Pkg commands"
  echo "  pkg help             # help info, all options and some tips"
  echo "  pkg help-all         # full help info, including advanced usage"
  echo
  echo " HINT: Use TAB to auto-complete package and repo names (and more).."
  echo
  echo '============================================================'

  # get the right list of repos
  update_sources &>/dev/null &

  # delete first run flag
  rm -f ~/.pkg/firstrun 2>/dev/null

  # delete other tmp stuff, make it like a first run
  rm $TMPDIR/func_list        &>/dev/null
  rm $TMPDIR/curr_repo_url    &>/dev/null
  rm $TMPDIR/internetsuccess  &>/dev/null
  rm $TMPDIR/pkg_aliases      &>/dev/null
  rm $TMPDIR/pkglist          &>/dev/null
  rm $TMPDIR/pkglist_*        &>/dev/null
  rm $TMPDIR/USRPKGLIST       &>/dev/null
  rm $TMPDIR/PKGSDONE         &>/dev/null
  rm $TMPDIR/deps_installed   &>/dev/null
  rm $TMPDIR/deps_missing     &>/dev/null
  rm $TMPDIR/$SELF-cp-errlog  &>/dev/null
  rm $TMPDIR/*-MISSING.txt    &>/dev/null
  
  exit 0
}

}
#====================  main functions  ======================#


{
#=====================  final checks  =======================#

# try to set a default repo if none was found
if [ ! -f "${HOME}/.packages/$REPOFILE" -o ! -f "$HOME/.pkg/sources" ];then
  
  mkdir -p $HOME/.pkg 2>/dev/null
  mkdir -p $HOME/.packages 2>/dev/null
  [ ! -f "$HOME/.pkg/sources" ] && touch $HOME/.pkg/sources
  # try to get repo file from /root if it exists
  if [ -f /root/.packages/Packages-puppy-noarch-official ];then
    # copy any available Puppy repo files in root to $HOME/.packages
    cp /root/.packages/Packages-puppy-* $HOME/.packages/
  fi
  
  # if repo file was NOT added to home dir, fata error, exit 
  if [ ! -f $HOME/.packages/Packages-puppy-noarch-official ];then
    error "Repo files not found. Check ${magenta}$HOME/.packages${endcolour}"
    exit 1
  fi

  # if we got here, the noarch repo file is in $HOME/.packages, lets use it as the default/only repo 
  #echo -e "${yellow}Warning:${endcolour} No repo files found. Setting the default repo to 'noarch'."
  update_sources 1>/dev/null
  set_current_repo noarch 1>/dev/null
  # if repos added ok
  if [ $? -eq 0 ];then
    echo -e "${green}Success:${endcolour} 'noarch' added."
    echo "Re-running: $SELF $@"
    echo 
    $SELF $@
    exit 0
  fi

fi

# create the user-installed pkgs file if it doesnt exists
[ ! -f $HOME/.packages/user-installed-packages ] && touch $HOME/.packages/user-installed-packages

first_run

}
#=====================  final checks  =======================#


{
#====================  main interface  ======================#

while [ $# != 0 ]; do # get all options ($# means all options)
   I=1
   while [ ! -z $# -a $I -le `echo $# | wc -c` ]; do
    
    # enable passing multiple pkgs separated by comma, space, 
    # works with or without double quotes around pkgs
    opt="`shift; echo "$@"`"
    opt="${opt//,/ }"
    opt="${opt//|/ }"
    # only keep params up to the next option
    opt="${opt// -*/}"

    ##accept stdin
    
    # accept from stdin, pkg -x -
    case $2 in 
      -)
        if [ "$3" = "" ];then
          while true; do
            read ALINE
            [ "$ALINE" ] || break
            [ "$(echo $ALINE| cut -b1)" = '#' ] && continue # skip comment
            [ "$ALINE" = ':' ] && continue  # skip colon
            if [ "$ALINE" = "- " -o "$ALINE" = " -" -o "$ALINE" != "-" ];then
              OPTS="${@%-}" #get all opts, without last dash
              OPTS="${OPTS% }" #get all opts, strip last space
              $SELF $OPTS "$ALINE"
            fi
          done
        fi
      ;; 
      --ask|-a)         export ASK=true ; export QTAG="?  (y/N)";;
      --quiet|-q)       export QUIET=true ;;
      --force|-f)       export FORCE=true ;;
      --no-color)       green='' red='' magenta='' lightblue='' yellow='' bold='' endcolour='' ;;
      --no-colour|-nc)  green='' red='' magenta='' lightblue='' yellow='' bold='' endcolour='' ;;
    esac
    
    # accept from stdin, pkg -x -x -
    case $3 in 
      -)
        if [ "$4" = "" ];then 
          while true; do
            read ALINE
            [ "$ALINE" ] || break
            [ "$(echo $ALINE| cut -b1)" = '#' ] && continue # skip comment
            ALINE=`echo $ALINE` #strip spaces
            OPTS="${@%-}"       #get all opts, without last dash
            OPTS="${OPTS% }"    #get all opts, strip last space
            $SELF $OPTS "$ALINE"
          done
        fi
      ;; 
      --ask|-a)         export ASK=true ; export QTAG="?  (y/N)";;
      --quiet|-q)       export QUIET=true ;;
      --force|-f)       export FORCE=true ;;
      --no-color)       green='' red='' magenta='' lightblue='' yellow='' bold='' endcolour='' ;;
      --no-colour|-nc)  green='' red='' magenta='' lightblue='' yellow='' bold='' endcolour='' ;;
    esac
    
    # accept from stdin, pkg -x- x- x -
    case $4 in 
      -)
        if [ "$5" = "" ];then 
          while true; do
            read ALINE
            [ "$ALINE" -a "$ALINE" != '-' ] || break
            [ "$(echo $ALINE| cut -b1)" = '#' ] && continue # skip comment
            ALINE=`echo $ALINE` #strip spaces
            OPTS="${@%-}"       #get all opts, strip last dash
            OPTS="${OPTS% }"    #get all opts, strip last space
            $SELF $OPTS "$ALINE"
          done
        fi
      ;; 
      --ask|-a)         export ASK=true ; export QTAG="?  (y/N)";;
      --quiet|-q)       export QUIET=true ;;
      --force|-f)       export FORCE=true ;;
      --no-color)       green='' red='' magenta='' lightblue='' yellow='' bold='' endcolour='' ;;
      --no-colour|-nc)  green='' red='' magenta='' lightblue='' yellow='' bold='' endcolour='' ;;
    esac

    # accept from stdin, pkg -x- x- x- x -
    case $5 in 
      -)
        if [ "$5" = "" ];then 
          while true; do
            read ALINE
            [ "$ALINE" -a "$ALINE" != '-' ] || break
            [ "$(echo $ALINE| cut -b1)" = '#' ] && continue # skip comment
            ALINE=`echo $ALINE` #strip spaces
            OPTS="${@%-}"       #get all opts, strip last dash
            OPTS="${OPTS% }"    #get all opts, strip last space
            $SELF $OPTS "$ALINE"
          done
        fi
      ;; 
      --ask|-a)         export ASK=true ; export QTAG="?  (y/N)";;
      --quiet|-q)       export QUIET=true ;;
      --force|-f)       export FORCE=true ;;
      --no-color)       green='' red='' magenta='' lightblue='' yellow='' bold='' endcolour='' ;;
      --no-colour|-nc)  green='' red='' magenta='' lightblue='' yellow='' bold='' endcolour='' ;;
    esac


    ## main options   
    case $1 in

      -) # accept from stdin, pkg -i (defaults to pkg -g $1 or pkg -u $1)
        if [ "$2" = "" ];then 
          while true; do
            read ALINE
            [ "$ALINE" -a "$ALINE" != '-' ] || break
            [ "$(echo $ALINE| cut -b1)" = '#' ] && continue # skip comment
            ALINE=`echo $ALINE` #strip spaces
            if [ "$ALINE" != "-" -a "`$PKGSEARCH "$ALINE"`" != "" ];then
              [ "`is_installed_pkg $ALINE`" = false ] && pkg_get "$ALINE" || \
              pkg_uninstall "$ALINE"
            fi
          done
          shift
        fi
      ;; 

      --ask|-a)         export ASK=true ; export QTAG="?  (y/N)";;
      --quiet|-q)       export QUIET=true ;;
      --force|-f)       export FORCE=true ;;
      --no-color)       green='' red='' magenta='' lightblue='' yellow='' bold='' endcolour='' ;;
      --no-colour|-nc)  green='' red='' magenta='' lightblue='' yellow='' bold='' endcolour='' ;;

      # package search
      --all-pkgs|--all|all)             [ ! "$2" ] && cat ${HOME}/.packages/${REPOFILE} || cat ${HOME}/.packages/${REPOFILE} | grep "$2"; exit 0;; 
      --search|-s|search|s)             [ ! "$2" ] && search_pkgs          || for x in "$opt"; do [ "$x" -a "$x" != "-" ] && search_pkgs "$x";         done; exit 0 ;; 
      -ss)                              [ ! "$2" ] && search_fast          || for x in "$opt"; do [ "$x" -a "$x" != "-" ] && search_fast "$x";         done; exit 0 ;; 
      --search-all|-sa|search-all|sa)   [ ! "$2" ] && search_all_pkgs      || for x in "$opt"; do [ "$x" -a "$x" != "-" ] && search_all_pkgs "$x";     done; exit 0 ;; 
      -ssa)                             [ ! "$2" ] && search_all_fast      || for x in "$opt"; do [ "$x" -a "$x" != "-" ] && search_all_fast "$x";     done; exit 0 ;; 
      --names|-n|names|n)               [ ! "$2" ] && list_pkg_names       || for x in $opt; do [ "$x" -a "$x" != "-" ] && list_pkg_names "$x";         done; exit 0 ;; 
      --names-exact|-ne|names-exact|ne) [ ! "$2" ] && list_pkg_names       || for x in $opt; do [ "$x" -a "$x" != "-" ] && list_pkg_names "$x\$";       done; exit 0 ;; 
      --names-all|-na|names-all|na)     [ ! "$2" ] && list_all_pkg_names   || for x in $opt; do [ "$x" -a "$x" != "-" ] && list_all_pkg_names "$x";     done; exit 0 ;; 
    --list-installed|-li|li)            [ ! "$2" ] && list_installed_pkgs  || for x in $opt; do [ "$x" -a "$x" != "-" ] && list_installed_pkgs "$x";    done; exit 0 ;; 
   --list-downloaded|-ld|ld)            [ ! "$2" ] && list_downloaded_pkgs || list_downloaded_pkgs "$2"; exit 0 ;;
      -LI|LI)                           [ ! "$2" ] && HIDE_BUILTINS=false list_installed_pkgs || for x in $opt; do HIDE_BUILTINS=false list_installed_pkgs "$x"; done ;; # list all installed pkgs inc builtins
  --names-exact-all|-nea|names-all-exact|nea) [ ! "$2" ] && list_all_pkg_names || for x in $opt; do [ "$x" -a "$x" != "-" ] && list_all_pkg_names "$x\$"; done; exit 0 ;;
       
      # get, download, install, remove, pkgs
      --download|-d|download|d)         [ ! "$2" ] && pkg_download || for x in $opt; do [ "$x" -a "$x" != "-" ] && pkg_download "$x";  done;; 
      --install|-i|install|i)           [ ! "$2" ] && pkg_install  || for x in $opt; do [ "$x" -a "$x" != "-" ] && pkg_install "$x";   done;; 
      --uninstall|-u|uninstall|u)       [ ! "$2" ] && pkg_uninstall|| for x in $opt; do [ "$x" -a "$x" != "-" ] && pkg_uninstall "$x"; done;; 
      --unpack|--extract|unpack|extract)[ ! "$2" ] && pkg_unpack   || for x in $opt; do [ "$x" -a "$x" != "-" ] && pkg_unpack "$x";    done;;
      --clean|clean)                    [ ! "$2" ] && clean_pkgs   || for x in $opt; do [ "$x" -a "$x" != "-" ] && clean_pkgs "$x";    done;;
      --get|-g|get|g)                   [ ! "$2" ] && pkg_get      || for x in $opt; do [ "$x" -a "$x" != "-" ] && { choose_pkg "$x"; pkg_get "$x"; }; done ;;  
      --get-only|-go|get-only|go)       [ ! "$2" ] && print_usage get-only || for x in $opt; do if [ "$x" -a "$x" != "-" ];then choose_pkg "$x"; NO_INSTALL=true  pkg_get "$x"; fi; done ;;  
      --delete|-l|delete|l)             [ ! "$2" ] && print_usage delete   || for x in $opt; do [ "$x" = '-' ] && continue; if [ -f "${WORKDIR}/$(basename "$x")" ];then if [ "$ASK" = true ];then echo -n "Remove package `basename $x`$QTAG "; read -n 1 CONFIRM </dev/tty; echo; else CONFIRM=y; fi; [ "$CONFIRM" = "y" ] && rm -v "${WORKDIR}/$(basename "$x")"; else not_found "$x"; fi; done ;; #110213,0.9.1  renamed to --delete|-l 
      --delete-all|-la|delete-all|la)   ASK=true; QTAG="?  (y/N)"; if [ "$ASK" = true ];then echo -en "Remove all downloaded packages in ${lightblue}${WORKDIR}/${endcolour}$QTAG"; read -n 1 CONFIRM </dev/tty; echo; else CONFIRM=y; fi; [ "$CONFIRM" = "y" ] && rm -v ${WORKDIR}/*.pet ${WORKDIR}/*.pkg.* ${WORKDIR}/*.sfs ${WORKDIR}/*.tar.* ${WORKDIR}/*.tcz ${WORKDIR}/*.txz ${WORKDIR}/*.tgz ${WORKDIR}/*.deb ${WORKDIR}/*.rpm ${WORKDIR}/*.apk ${WORKDIR}/*.gz ${WORKDIR}/*.xz 2>/dev/null; exit 0;;
      --install-all|-ia)                list_downloaded_pkgs | while read pkg; do [ "$pkg" -a "$pkg" != "-" ] && pkg_install "$pkg";   done;;
      --uninstall-all|-ua)              list_installed_pkgs  | while read pkg; do [ "$pkg" -a "$pkg" != "-" ] && pkg_uninstall "$pkg"; done;;

      # pkg status, info
      --pkg-installed|-pi|installed|pi)   [ ! "$2" ] && is_installed_pkg || for x in $opt; do [ "$x" -a "$x" != "-" ] && is_installed_pkg "$x"; done;;
      --pkg-entry|-pe|entry|pe)           [ ! "$2" ] && pkg_entry   || for x in $opt; do [ "$x" -a "$x" != "-" ] && pkg_entry "$x";    done;;  # print repo entry, each field on a new line
      --pkg-status|-ps|status|ps)         [ ! "$2" ] && pkg_status  || for x in $opt; do [ "$x" -a "$x" != "-" ] && pkg_status "$x";   done;;
      --contents|-c|contents|c)           [ ! "$2" ] && pkg_contents|| for x in $opt; do [ "$x" -a "$x" != "-" ] && pkg_contents "$x"; done;;
      --which|-w|which|w)                 [ ! "$2" ] && which_pkg   || for x in $opt; do [ "$x" -a "$x" != "-" ] && which_pkg "$x";    done;;
      --which-repo|-wr|which-repo|wr)     [ ! "$2" ] && which_repo  || for x in $opt; do [ "$x" -a "$x" != "-" ] && which_repo "$x";   done;;
      --pkg-repack|-pr|repack|pr)         [ ! "$2" ] && pkg_repack  || for x in $opt; do [ "$x" -a "$x" != "-" ] && pkg_repack "$x";   done;;
      --pkg-update|-pu|update|pu)         [ ! "$2" ] && pkg_update  || for x in $opt; do [ "$x" -a "$x" != "-" ] && pkg_update "$x";   done;;
      --pkg-combine|-pc|pkg-combine|pc)   [ ! "$2" ] && pkg_combine || for x in $opt; do [ "$x" -a "$x" != "-" ] && COMBINE2SFS=false pkg_combine "$x"; done;;
      --sfs-combine|-sc|sfs-combine|sc)   [ ! "$2" ] && pkg_combine || for x in $opt; do [ "$x" -a "$x" != "-" ] && COMBINE2SFS=true  pkg_combine "$x"; done;;
      -PS|PS)                             [ ! "$2" ] && pkg_status  || for x in $opt; do [ "$x" -a "$x" != "-" ] && HIDE_USER_PKGS=false FULL_PKG_STATUS=true pkg_status "$x"; done;; # full pkg status, with sorted deps

      # pkg compiling
      --pkg-build|-pb|build|pb)           [ ! "$2" ] && pkg_build || for x in $opt; do [ "$x" -a "$x" != "-" ] && pkg_build "$x"; done;;
   --pkg-build-list|-pbl|build-list|pbl)  [ ! "$2" ] && list_build_scripts || for x in $opt; do [ "$x" -a "$x" != "-" ] && list_build_scripts "$x"; done;;
      
      # dependencies
      --what-needs|-wn|what-needs|wn)     [ ! "$2" ] && list_dependents; for x in $opt; do [ "$x" -a "$x" != "-" ] && list_dependents "$x"; done ;; # list pkgs depending on $x, not including builtins by default
      --list-deps|-le|list-deps|le)       [ ! "$2" ] && list_deps; for x in $opt; do [ "$x" -a "$x" != "-" ] && list_deps "$x"; done ;; # list pkg deps, not including builtins
      --deps|-e|deps|e)                   [ ! "$2" ] && get_deps;  for x in $opt; do [ "$x" -a "$x" != "-" ] && get_deps  "$x"; done ;;
    --deps-download|-ed|deps-download|ed) [ ! "$2" ] && get_deps;  for x in $opt; do [ "$x" -a "$x" != "-" ] && NO_INSTALL=true get_deps "$x"; done ;;
      --has-deps|-he|has-deps|he)         [ ! "$2" ] && has_deps;  for x in $opt; do [ "$x" -a "$x" != "-" ] && has_deps  "$x"; done ;;
      --deps-all|-ea|deps-all|ea)         [ ! "$2" ] && get_deps;  [ "$2" != "-" ] && NO_INSTALL=false get_all_deps "$2" ;;
      --deps-check|-ec|depscheck|ec)      [ ! "$2" ] && print_usage deps-check || pkg_ldd_msg "$2" ;;
      -LE|LE)                             [ ! "$2" ] && HIDE_BUILTINS=false list_deps || for x in $opt; do [ "$x" -a "$x" != "-" ] && HIDE_BUILTINS=false list_deps "$x"; done ;;  # list a pkg deps, including builtins
       
      # repo
      --repo|-r|repo|r)                     [ ! "$2" ] && echo $REPONAME || set_current_repo "$2" ;; 
      --repo-convert|-rc|repo-convert|rc)   [ ! "$2" ] && print_usage repo-convert || for x in $opt; do [ "$x" -a "$x" != "-" ]  && convert_repofile "$x"; done ;;
      --repo-list|-rl|repo-list|rl)         [ "$2" != "-" ] && repo_list "$2"      ;;
      --repo-info|-ri|repo-info|ri)         [ "$2" != "-" ] && print_repo_info "$2";;
  --repo-file-list|-rfl|repo-file-list|rfl) [ "$2" != "-" ] && repo_file_list "$2" ;;
      --repo-update|-ru|repo-update|ru)     update_repo "$2";;
      --add-source|add-source)              [ "`echo $2|grep '|'`" = '' -o "$2" = '-' ] && print_usage add-source || add_source "$2";; 
      --update-sources|update-sources)      update_sources ;; 

      # set repo settings
      --repo-pkg-scope|-rps)  if [ "$2" -a "$2" != "-" ];then set_pkg_scope "$2";      else echo "$PKGSCOPE"; fi; exit 0;;
      --repo-dep-scope|-rds)  if [ "$2" -a "$2" != "-" ];then set_dep_scope "$2";      else echo "$DEPSCOPE"; fi; exit 0;;
      --bleeding-edge|-be)    if [ "$2" -a "$2" != "-" ];then set_bleeding_edge "$2";  else echo "$BLEDGE";   fi; exit 0;;
  --recursive-dep-check|-rdc) if [ "$2" -a "$2" != "-" ];then set_recursive_deps "$2"; else echo "$RDCHECK";  fi; exit 0;; 
       
      # convert
      --deb2pet|deb2pet) [ ! "$2" ] && deb2pet || for x in $opt; do deb2pet "$x"; done ;;
      --dir2pet|dir2pet) [ ! "$2" ] && dir2pet || for x in $opt; do dir2pet "$x"; done ;;
      --dir2sfs|dir2sfs) [ ! "$2" ] && dir2sfs || for x in $opt; do dir2sfs "$x"; done ;;
      --dir2tgz|dir2tgz) [ ! "$2" ] && dir2tgz || for x in $opt; do dir2tgz "$x"; done ;;
      --pet2sfs|pet2sfs) [ ! "$2" ] && pet2sfs || for x in $opt; do pet2sfs "$x"; done ;;
      --pet2tgz|pet2tgz) [ ! "$2" ] && pet2tgz || for x in $opt; do pet2tgz "$x"; done ;;
      --pet2txz|pet2txz) [ ! "$2" ] && pet2txz || for x in $opt; do pet2txz "$x"; done ;;
      --sfs2pet|sfs2pet) [ ! "$2" ] && sfs2pet || for x in $opt; do sfs2pet "$x"; done ;;
      --tgz2pet|tgz2pet) [ ! "$2" ] && tgz2pet || for x in $opt; do tgz2pet "$x"; done ;;
      --txz2pet|txz2pet) [ ! "$2" ] && txz2pet || for x in $opt; do txz2pet "$x"; done ;;
       
      # other
      --func-list)    [ -f $TMPDIR/func_list ] && cat $TMPDIR/func_list || func_list; exit 0;;
      --workdir)      [ "$2" != "-" ] && set_workdir "$2"; exit $?;;
      --autoclean)    [ "$2" = "yes" -o "$2" = "no" ] && set_autoclean "$2" || { echo "$AUTOCLEAN"; exit 1; } ;;
      
      # usage, help funcs, version info, etc
      --welcome|welcome)          touch $HOME/.pkg/firstrun; first_run; exit 0;;
      --show-config|show-config)  show_config; exit 0;;
      --version|-v|version|v)     echo "$APPNAME $APPVER"; exit 0;;
      --usage|usage)              print_usage "$2"; exit 0;;
      
      --examples|-ex|examples|ex) 
        . /usr/lib/pkg/docs/examples.txt;
        echo -e "$EXAMPLES\n"
        exit 0
        ;;
      --help-all|-H|help-all|H)  
          . /usr/lib/pkg/docs/help.txt
          . /usr/lib/pkg/docs/examples.txt
          . /usr/lib/pkg/docs/help-all.txt
          echo -e "$HELP_ALL\n\n" | less -R
          exit 0
          ;;
          
      --help|-h|help|h) 
          . /usr/lib/pkg/docs/help.txt
          echo -e "$HELP\n"
          exit 0
          ;;

      # any other options
      -?*|--?*) 
          # exit if bad options
          echo "Unknown option '$1'" && exit 1
        ;; 

      ?*) 
          # all other options .. might be an internal func, if so, execute it with all given options
          [ "`func_list | tr '\t' ' ' | cut -f2 -d' ' | grep -m1 "^${1}"'()'`" != '' ] && "$@" && exit 0
        ;;

      esac

      shift
      I=$(($I + 1))
    done
done


}
#====================  main interface  ======================#
code=$?

# if AUTOCLEAN=true silently delete all pkgs in WORKDIR that are already installed
if [ "$AUTOCLEAN" = 'yes' -a "`HIDE_BUILTINS=true list_installed_pkgs`" != '' ];then
  clean_pkgs &>/dev/null
fi

# remove tmp dir used by pkg_get and get_deps
rm $TMPDIR/PKGSDONE 2>/dev/null

# reset lang options as we found them
LANG=$USER_LANG
LC_ALL=$USER_LC_ALL

exit $code
