# PaCkAgE DaTaStReAm BOLTpget 1 156 # end of header 0707011c5eb28f000081a4000002bc00000001000000013cbef3c3000001920000000000000002ffffffffffffffff0000001100000006BOLTpget/pkginfoARCH=all CLASSES=none BASEDIR=/usr PATH=/sbin:/usr/sbin:/usr/bin:/usr/sadm/install/bin PKG=BOLTpget NAME=pkg-get VERSION=1.9.5 CATEGORY=system DESC=A convinient way to automate package install from sunfreeware.com VENDOR=Philip Brown, Bolthole Software, http://www.bolthole.com EMAIL=phil@bolthole.com URL=http://www.bolthole.com/solaris/ PKGSAV=/var/sadm/pkg/BOLTpget/save PSTAMP=zaphod20020418092643 0707011c5eb227000081a4000002bc00000001000000013cbef3c30000018b0000000000000002ffffffffffffffff0000001000000006BOLTpget/pkgmap: 1 156 1 d none /var ? ? ? 1 d none /var/pkg-get 0755 root bin 1 f none /var/pkg-get/admin-fullauto 0755 root bin 468 42766 1016264596 1 d none bin ? ? ? 1 f none bin/pkg-get 0755 root bin 31217 38858 1019147200 1 i pkginfo 402 34529 1019147203 1 d none share ? ? ? 1 d none share/man ? ? ? 1 d none share/man/man1m ? ? ? 1 f none share/man/man1m/pkg-get.1m 0755 root bin 5426 28080 1018984185 07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000b00000000TRAILER!!!0707011c5eb28f000081a4000002bc00000001000000013cbef3c3000001920000000000000002ffffffffffffffff0000000800000006pkginfoARCH=all CLASSES=none BASEDIR=/usr PATH=/sbin:/usr/sbin:/usr/bin:/usr/sadm/install/bin PKG=BOLTpget NAME=pkg-get VERSION=1.9.5 CATEGORY=system DESC=A convinient way to automate package install from sunfreeware.com VENDOR=Philip Brown, Bolthole Software, http://www.bolthole.com EMAIL=phil@bolthole.com URL=http://www.bolthole.com/solaris/ PKGSAV=/var/sadm/pkg/BOLTpget/save PSTAMP=zaphod20020418092643 0707011c5eb227000081a4000002bc00000001000000013cbef3c30000018b0000000000000002ffffffffffffffff0000000700000006pkgmap: 1 156 1 d none /var ? ? ? 1 d none /var/pkg-get 0755 root bin 1 f none /var/pkg-get/admin-fullauto 0755 root bin 468 42766 1016264596 1 d none bin ? ? ? 1 f none bin/pkg-get 0755 root bin 31217 38858 1019147200 1 i pkginfo 402 34529 1019147203 1 d none share ? ? ? 1 d none share/man ? ? ? 1 d none share/man/man1m ? ? ? 1 f none share/man/man1m/pkg-get.1m 0755 root bin 5426 28080 1018984185 0707011c282ab7000041ed000002bc00000001000000043cbef3c3000000000000000000000002ffffffffffffffff0000000600000006reloc0707011c32d36e000041ed000002bc00000001000000023cbef3c3000000000000000000000002ffffffffffffffff0000000a00000006reloc/bin0707011c628c90000081a4000002bc00000001000000013cbef3c0000079f10000000000000002ffffffffffffffff0000001200000006reloc/bin/pkg-get#!/bin/ksh -p # the -p says "ignore profile" # This is loosely modeled after debian "apt-get". # Philip Brown, phil@bolthole.com, http://www.bolthole.com/solaris/ # MASTERSITE is always the fallback. # Precedence is: commandline, conf file, fallback MASTERSITE=ftp.sunfreeware.com SITE=$MASTERSITE # "WGET" needs to be set to something that # 1. can do wildcarding ftp gets # 2. will dump the file to stdout # 3. will handle file:// urls as well as ftp stuff. # If you really think you have a replacement, you can actually # override this var in /etc/pkg-get.conf WGET=${WGET:-grabfunc} # If you prefer something else than wget, feel free to substitute! :-) ###################################################################### # Dont change anything below here # # # Since sunfreeware always installs to /usr/local, make sure it is in path, # for wget purposes. case $PATH in */usr/local/bin*) ;; *) PATH=$PATH:/usr/local/bin esac # Then again, theres an off-chance it may be in /opt/sfw/bin if [[ -x /opt/sfw/bin/wget ]] ; then PATH=$PATH:/opt/sfw/bin fi # Grab file, and dump it to stdout # But this is a special wrapper to handle file:// urls # grabfunc(){ graburl="$1" if [[ $# -eq 2 ]] ; then graburl="$2"; fi if [[ $# -eq 3 ]] ; then graburl="$3"; fi case $graburl in file://*) fname=${graburl#file://} # if multiple match to wildcard only use first one fname=${fname%% *} fname=$(print $fname) if [[ ! -f $fname ]] ; then print ERROR: file $fname does not exist >/dev/fd/2 return 1 fi cat $fname return 0 ;; esac # else #-nv means NO progress meter at all. You dont get the dots. # wget -nv --dot-style=mega --passive-ftp -O /dev/fd/1 $* wget --dot-style=mega --passive-ftp -O /dev/fd/1 $* } CONFFILE=/etc/pkg-get.conf CHEATDIR=/var/sadm/pkg if [[ ! -f $CONFFILE ]] ; then print ERROR: $CONFFILE not present print Creating a default file cat >$CONFFILE < 1 2 # beta ==> beta # beta3 ==> beta 3 # WARNING: WILL ALWAYS print out ' ' as minimum!!! trimrev(){ if [[ "$1" == "" ]] ; then print " " return fi # if string starts with a number, the return leading number. # Otherwise, return initial letter tag, like "beta", or whatever. # THis is for potential comparison between "alpha" and "beta" case $1 in [0-9]*) echo $1 | sed 's/^\([0-9][0-9]*\)[-_.+]*\(.*\)/\1 \2/' return esac # No leading digits, so split off leading ascii echo $1 | sed 's/^\([^0-9]*[^0-9]*\)[-_.+]*\(.*\)/\1 \2/' } # Pass in two strings. # Return (print) longest string that is common to both of them trimshared(){ if [[ $# -lt 2 ]] ; then print ERROR: trimshared needs TWO args exit 1 fi savedstring=""; while [[ 1 -eq 1 ]] ; do one_end=${1##?} two_end=${2##?} trimsnip=${1%%$one_end} if [[ "$trimsnip" == "" ]] ; then print $savedstring return fi case $2 in ${trimsnip}*) set "$one_end" "$two_end" savedstring=${savedstring}${trimsnip} ;; *) # default print $savedstring return esac done } # newer_rev rev1 rev2 # Returns true (0) if rev1 is newer than rev2 # Otherwise, return false (1) # Up to caller to only pass in revision id. # from a filename "GNU-tar-v2.13.tar.gz" only pass in "v2.13" newer_rev(){ remainder1=""; remainder2="" if [[ $# -lt 2 ]] ; then print Need TWO args to newer_rev exit 1 fi # First, snip off common string at the front rev_shared=`trimshared $1 $2` if [[ "$rev_shared" != "" ]] ; then val1=${1##$rev_shared} val2=${2##$rev_shared} set "$val1" "$val2" fi val1="$1" val2="$2" # Now, split off leading numeric components tmprev=`trimrev $val1` if [[ "$tmprev" != " " ]] ; then set $tmprev val1=$1 remainder1=$2 else val1="" ; remainder1="" fi tmprev=`trimrev $val2` if [[ "$tmprev" != " " ]] ; then set $tmprev val2=$1 remainder2=$2 else val2="" ; remainder2="" fi if startsnumeric $val1 && startsnumeric $val2 ; then if [[ $val1 -gt $val2 ]] ; then return 0 fi if [[ $val1 -lt $val2 ]] ; then return 1 fi # have same digits. Do recursion on remainder newer_rev "$remainder1" "$remainder2" return $? fi # Otherwise, we have something like # 1.1alpha vs 1.1beta, I think. # or [1.1] vs [1.1]"beta" # OR 1.1.1 vs 1.1 # Note that if 1.1 vs 1.1.1, second arg will be truncated to ".1". # trimrev will return val2=. and ]remainder2[ will have # the numeric value. # If there is something extra for #1, and not for #2, then # it may be a 'beta' suffix, which means #1 is # OLDER, not newer if [[ "$val2" == "" ]] ; then if startsnumeric $remainder1 ; then return 0 # yes, $1 is greater! else return 1 # nope. got beta or similar suffix: bad fi fi #and now the mirror case if [[ "$val1" == "" ]] ; then if startsnumeric $remainder2 ; then return 1 else return 0 fi fi print "WARNING: dont know how to compare ascii strings $val1 $val2" >/dev/fd/2 return 1; } ###################################################################### # End of software name version comparision code # ###################################################################### ###################################################################### # This expects a REAL "pkg" name, eg PKGINST name, eg "SUNWapchd" # It then looks up the VERSION field, and prints it to stdout # return 1 if not installed, 0 otherwise. get_pkg_versionfield(){ #pkgname="$1" vtmp=`pkginfo -l $1 | awk '$1 == "VERSION:" {print $2}'` if [[ "$vtmp" == "" ]] ; then return 1 fi case $vtmp in *,*) # Arrg. Sun was "creative" with version string vtmp=${vtmp%%,*} esac print $vtmp } # This expects a SOFTWARENAME string, not a package name # It will then check the catalog for versions of that software bundle, # and return the version field for the version in the catalog. # Normally, if there are multiple versions available, it will return the # 'MULTIPLE' flag. # However, if we are in upgrade mode, it will just return the # highest-rev version available (I hope) # get_remote_version(){ remver=`awk '$1 ~ /^#/ {next} $1 == "'$1'" { print $2; }' $CATALOGFILE` count=0 for rev in $remver ; do count=$(($count + 1)) done if [[ $count -le 1 ]] ; then print $remver return fi if [ $do_upgrade -eq 0 ] ; then print MULTIPLE $remver return fi # We are in upgrade mode! for rev in $remver ; do if [[ "$maxver" == "" ]] ; then maxver=$rev continue fi #print DEBUG: get_remote_version calling newer_rev >/dev/fd/2 newer_rev $rev $maxver if [ $? -eq 0 ] ; then maxver=$rev fi done print $maxver } #call this with # explain_multiple softwarename MULTIPLE ver1 ver2 explain_multiple_install(){ if [[ $# -lt 4 ]] ; then print INTERNAL ERROR: explain multiple called badly print \"explain_multiple $* \" return fi print "Sorry, there are multiple versions possible" print "Please specify one, in the following syntax" software="$1" shift ; shift while [[ $# -gt 0 ]] ; do print pkg-get $mode ${software}-$1 shift done } explain_multiple_remove(){ print "Sorry, there are multiple SysV pkgs installed" print "This is usually not possible, if pkg-get is used." print "You will have to resolve this by hand, [with pkgrm]" print "or try being more specific about the version of software" print "" print "The following related SysV packages have been detected" print $* } # Given a software (NOT pkg) name, and a revision number, # generate a filename. prints out exact filename if available, # or a wildcard pattern. # $1=software, $2=revnum get_filename(){ net_name=`nawk '$1 == "'$1'" && $2 == "'$2'" {print $4}' $CATALOGFILE` if [[ -z "$net_name" ]] ; then print ERROR: could not find filename for $1 $2 >/dev/fd/2 exit 1 fi print "${net_name}" } # # Top level routine for "pkg-get upgrade" # If no argument is given, tries to download and pkgadd newer versions # of every single net package already installed. # If # If a specific software name is given, download latest version upgrade() { do_upgrade=1 #global var if [[ "$1" == "" ]] ; then set `egrep -v '^#' $CATALOGFILE | awk '{print $1}'|sort -u` print note: upgrading ALL INSTALLED PACKAGES for name in $* ; do pkgname=`awk '$1 == "'$name'" {print $3; exit;}' $CATALOGFILE` if [[ -d $CHEATDIR/$pkgname ]] ; then upgradelist="$name $upgradelist" fi done print Installed software packages: print $upgradelist set $upgradelist fi # Since user specified specific packages, try to # install/upgrade those for name in $* ; do install_one_pkg "$name" done } # Given a SysV pkg name, look up the software package name for it in # our catalog. # print out result, or return 1 if not found find_software_name(){ findname="$1" sftname=`awk '$1 ~ /^#/ {next} $3 == "'$findname'" { print $1 }' $CATALOGFILE` if [[ "$sftname" == "" ]] ; then return 1 fi print $sftname } # called by both install_one_pkg, and remove_pkg # Given a common name for a software package, figure out the # SysV pkg name and print it, or print "",and an errormesasge # to stderr. # It is POSSIBLE it may return multiple SysV names. # remove_pkg() actually tries to take advantage of this. # # So if you want a guaranteed single return print, it is best to call it # with a second argument, giving the specific package version name. # find_pkg_name(){ findname="$1" if [[ "$2" == "" ]] ; then pkgname=`awk '$1 ~ /^#/ {next} $1 == "'$findname'" { print $3 }' $CATALOGFILE` else pkgname=`nawk '$1 ~ /^#/ {next} $1 == "'$findname'" && $2 == "'$2'" { print $3 }' $CATALOGFILE` fi if [[ "$pkgname" == "" ]] ; then # try name-version syntax now # assume XXX-YY-ZZ is XXX, ver YY-ZZ soft=${findname%%-*} find_version=${findname#*-} pkgname=`awk '$1 ~ /^#/ {next} $1 == "'$soft'" && $2 == "'$find_version'" { print $3 }' $CATALOGFILE` # if [[ "$pkgname" != "" ]] ; then # findname="$soft" # fi # print DEBUG: after version decode # print findname=$findname # print pkgname=$pkgname # print find_version=$find_version fi # Still no match? if [[ "$pkgname" == "" ]] ; then print ERROR: no matching SysV PKG found. >/dev/fd/2 print $pkgname $soft $find_version >/dev/fd/2 print '(either you mistyped it, or you need to 'updatecatalog', or' >/dev/fd/2 print ' it isnt available for your OSREV yet)' >/dev/fd/2 return fi print $pkgname } # called by install_pkg # Must have one and only one argument: the name of a software package. # eg "bison" # This is NOT to be confused with a pkgname, like SUNWcar # We try to find the actual pkgname from the $CATALOG file # We then call net_install to download and install the actual package, # if it is a valid target for install # (or just return, doing nothing, otherwise) # install_one_pkg(){ if [[ "$1" == "" ]] ; then print INTERNAL ERROR: install_one_pkg has no args exit 1 fi i_sftname="$1" i_remversion="" case $i_sftname in *-*) i_remversion=${i_sftname#*-} i_sftname=${i_sftname%%-*} ;; esac # XXX should check for conflicts/multiples here if [[ "$i_remversion" == "" ]] ; then i_remversion=`get_remote_version $i_sftname` if [[ "$i_remversion" == "" ]] ; then print ERROR: $i_sftname unrecognized >/dev/fd/2 print Perhaps you need to run pkg-get -U>/dev/fd/2 exit 1 fi fi case "$i_remversion" in MULTIPLE*) explain_multiple_install $i_sftname $i_remversion >/dev/fd/2 return ;; esac pkgname=`find_pkg_name $1 $i_remversion` if [[ "$pkgname" == "" ]] ; then return fi if [[ "$downloadonly" -eq 1 ]] ; then # net_install checks downloadonly also net_install `get_filename $i_sftname $i_remversion` return fi # else... i_currversion=`get_pkg_versionfield $pkgname` if [[ $? -ne 0 ]] ; then print No existing install of $pkgname found. Installing... >/dev/fd/2 net_install `get_filename $i_sftname $i_remversion` return fi if [[ "$i_remversion" == "$i_currversion" ]] ; then print "No worries... you already have version $i_remversion of $i_sftname" print "If you doubt this message, run 'pkg-get -U', then run" print " 'pkg-get upgrade $i_sftname'" return fi newer_rev $i_remversion $i_currversion if [ $? -ne 0 ] ; then print "ERROR: remote version older than current version." print "Not installing remote package of $i_sftname" print "(remote=$i_remversion, local=$i_currversion)" return fi net_install `get_filename $i_sftname $i_remversion` } # Top routine for "pkg-get install" # Recognizes : # No arguments == update all installed packages # One or more arguments == treat each argument as a software name, # and try to either install or update it, as appropriate install_pkg(){ softwarename="$1" if [[ "$softwarename" == "" ]] ; then print Please specify packages you want installed. print "if you want 'all' packages installed, use" print " pkg-get install all" return fi if [[ "$softwarename" == "all" ]] ; then set `egrep -v '^#' $CATALOGFILE | awk '{print $1}'|sort -u` # using 'upgrade' ensures we install only the latest versions print "Installing ALL AVAILABLE SOFTWARE" upgrade $* return fi for name in $* ; do install_one_pkg "$name" done } # Given a SysV package name, recursively remove *ALL* # instances of it. # silently do nothing, if no instance is installed. remove_sysv_pkg() { rm_pkgname="$1" # Sneaky check for orphaned packages or something # We do NOT LIKE the funny .x instance names of packages if [[ -d /var/sadm/pkg/$rm_pkgname.2 ]] ; then print Removing old instance of $rm_pkgname pkgrm $ADMINFLAG $rm_pkgname.2 fi if [[ -d /var/sadm/pkg/$rm_pkgname ]] ; then print Removing old instance of $rm_pkgname pkgrm $ADMINFLAG $rm_pkgname fi } # Given a common-name for a package, figure out the SysV pkg name # and pkgrm it remove_pkg() { rm_softname="$1" rm_version="" case $rm_softname in *-*) rm_version=${rm_softname#*-} rm_softname=${rm_softname%%-*} ;; esac rm_pkgname=`find_pkg_name $rm_softname $rm_version` if [[ "$rm_pkgname" == "" ]] ; then return fi set $rm_pkgname rm_pkgname="$1" # First, look at all the externally possible unique pkgnames while [[ "$2" != "" ]] ; do if [[ "$2" != "$1" ]] ; then rm_pkgname="$rm_pkgname $2" fi shift done # Then see how many of them are actually INSTALLED set $rm_pkgname if [[ "$2" != "" ]] ; then while [[ "$1" != "" ]] ; do version=`get_pkg_versionfield $1` if [[ "$version" != "" ]] ; then rm_pkgname="$rm_pkgname $1" fi shift done fi set $rm_pkgname if [[ "$2" != "" ]] ; then explain_multiple_remove $rm_pkgname >/dev/fd/2 return fi remove_sysv_pkg $rm_pkgname } # Given a common name for a software package, hand it off to # remove_pkg remove_packages(){ if [[ "$1" == "" ]] ; then print ERROR: no packages given to remove exit 1 fi print "WARNING: the remove option is not very intelligent." print "If there are multiple versions of a package with the same" print "PKG style name, it will remove the first one it can" print "(will continue in 5 seconds)" sleep 5 print "Starting remove operations now..." print "" for name in $* ; do remove_pkg "$name" done } # Passed in a 'depend' file as arg 1. # parse it, and try to install any missing dependancies. # XXX this wont handle dependancies with revisions, currently. # # return 1 on fail install_dependancies(){ dependlist=`awk ' $1 == "P" {print $2}' $1` for dependpkg in $dependlist ; do pkginfo $dependpkg 2>/dev/null if [[ $? -ne 0 ]] ; then # Dependancy not installed. So install it. if [[ "$DIRECTORY" != "" ]] ; then # no point in using upgrade: # can only be one pkgname in a dir. $0 install $DIRECTORY $dependpkg continue fi # otherwise, we have to go through this whole # long thing of looking up the name, # so we can use pkg-get to install by softwarename. # dependname=`find_software_name $dependpkg` if [[ $? -ne 0 ]] ; then print ERROR: no info for $dependpkg. Cannot install dependancy. return 1 fi print Trying to install dependancy $dependname # XXX would be nice if we knew a specific version # to install. Otherwise, if multiple, get the newest. if [[ "$url" != "" ]] ; then $0 -s $url upgrade $dependname else $0 upgrade $dependname fi #did it work? pkginfo $dependpkg 2>/dev/null if [ $? -ne 0 ] ; then print ERROR: install of $dependpkg failed return 1 fi fi done } # Given a filename for a pkg, gzipped or not, pkgadd it, and # remove the file when done. # We first do a pkgtrans to /var/spool/pkg so we can check # dependancies by HAND. # # If there are unmet dependancies, try to grab them, # by invoking pkg-get in a SEPARATE process, so that # variable names dont conflict. # However, we can only install dependancies if they are from the same # site, since we need to look up software name from pkgname. # # If do_upgrade is set, remove any older version of pkg before doing install # # It is up to the calling function to determine whether the supplied file # is a higher rev than any existing package. We just remove all package # instances with the same sysv_pkg name. install_pkg_file() { filename="$1" file $filename | grep 'compressed ' >/dev/null if [[ $? -eq 0 ]] ; then gzip -d -c $filename >$filename.tmp mv -f $filename.tmp $filename fi pkgname=`awk 'NR==2 {print $1;exit}' $filename` if [[ $do_upgrade -eq 1 ]] ; then remove_sysv_pkg $pkgname fi # convert from file to to "spool" format, to check depends. # pkgtrans will quit if there already is one there. pkgtrans $filename /var/spool/pkg $pkgname if [ $? -ne 0 ] ; then return 1 fi if [ -f /var/spool/pkg/$pkgname/install/depend ] ; then install_dependancies /var/spool/pkg/$pkgname/install/depend if [ $? -ne 0 ] ; then print ERROR: could not install required dependancies for $pkgname /bin/rm -r /var/spool/pkg/$pkgname return 1 fi fi pkgadd $ADMINFLAG $pkgname status=$? if [[ $status -ne 0 ]] ; then print ERROR: could not add $pkgname. fi rm $filename /bin/rm -r /var/spool/pkg/$pkgname return $status } # grab either gzip or wget "the hard way" # return 0 on okay, 1 on fail ftp_prog_hardway(){ progname="$1" print Press return or enter email when asked for a password sleep 2 mkdir /tmp/ftp.tmp cd /tmp/ftp.tmp rm -f * rootcheck=`ls -ld | awk '{print $3}'` if [[ "$rootcheck" != "root" ]] ; then print SECURITY ERROR: /tmp/ftp.tmp not owned by ROOT #exit 1 fi ftp -id $MASTERSITE </dev/null if [[ $? -eq 0 ]] ; then return ; fi print "ERROR: gzip not in path. Install(y/n)?" read ans case $ans in y|Y) ;; *) print Quitting exit 1 ;; esac ftp_prog_hardway gzip status=$? if [[ $status -ne 0 ]] ; then print Pkgadd of gzip failed. Cannot continue exit 1 fi print "" return 0 } # Checks if we have wget. If not, tries to get it. # If cannot get, fails entire progam check_wget() { whence wget >/dev/null if [[ $? -eq 0 ]] ; then return ; fi print ERROR: cannot find wget. Attempting to install ftp_prog_hardway wget status=$? if [[ $status -eq 0 ]] ; then print "wget added successfully" print "" return fi print " " Recommend you install wget from print " " $fullurl/'wget*gz' print " " ftp the file, gunzip it, and then print " " 'pkgadd -d wget*' exit 1 } # Currently takes as args # 1. descriptive software name # 2. PKGname # 3. revisionnum # # Currently called by upgradeall, and install_one_pkg # Will download a package, and install it using install_pkg_file() # net_install() { net_name="$1" fullurl=$url/$CPU/$OSREV check_wget graburl=$fullurl/$net_name print trying $graburl case $graburl in *\*) print ERROR: no wildcards allowed in net_install exit ;; esac tmpfile=$net_name.tmp $WGET $graburl >$tmpfile if [[ $? -ne 0 ]] || [[ ! -s $tmpfile ]] ; then print error downloading $graburl rm $tmpfile return fi if [[ "$downloadonly" -eq 1 ]] ; then mv $tmpfile $net_name print downloaded package to $net_name return fi # else... really install install_pkg_file $tmpfile # install_pkg_file will remove tmp file } # This takes info for a SINGLE PACKAGE, and compares it to # what is locally available. # The printout format must match the header in show_installed() # Expects: # compare_pkg softwarename availablerev pkgname compare_pkg() { software="$1" rem_rev="$2" pkgname="$3" # gzip triggers this. if [[ "$pkgname" == "" ]] ; then # print ERROR: compare_pkg did not get all arguments passed # print "[" $* "]" return 1 fi if [[ ! -d $CHEATDIR/$pkgname ]] ; then localrev='[Not installed]' else localrev=`get_pkg_versionfield $pkgname 2>/dev/null` fi if [[ "$localrev" == "$rem_rev" ]] ; then rem_rev="SAME" fi printf "%15s %15s %15s\n" "$software" "$localrev" "$rem_rev" } # This cross-references all known install packages that match # the catalog file, with the installed version, vs the potential version show_installed() { print "# (From site $SITE )" printf "%15s %15s %15s\n" "software" "localrev" "remoterev" egrep -v '^#' $CATALOGFILE | while read line ; do compare_pkg $line done } update_catalog() { OSREV=$OSREV CPU=$CPU TMPDIR=/tmp/pkg.$$ TMPFILE=$TMPDIR/catalog if [[ ! -d /var/pkg-get ]] ; then print Warning: making /var/pkg-get mkdir /var/pkg-get fi check_wget mkdir /tmp/pkg.$$ if [[ $? -ne 0 ]] ; then print error making temp dir rmdir $TMPDIR exit 1 fi print Getting catalog... $WGET $url/$CPU/$OSREV/catalog > $TMPFILE if [[ $? -ne 0 ]] ; then print ERROR: could not get catalog file rm $TMPFILE rmdir $TMPDIR exit 1 fi if [[ ! -s $TMPFILE ]] ; then print ERROR: catalog file is zero length rm $TMPFILE rmdir $TMPDIR exit 1 fi print "Updating catalog file, EXCLUDING gzip" egrep -v '^(gzip)' $TMPFILE >$CATALOGFILE rm $TMPFILE rmdir $TMPDIR print $CATALOGFILE updated } ################################################### # main routine if [[ "$1" == "" ]] ; then usage exit 1 fi # MUST HAVE gzip! Try to grab, if needed check_gzip ###################################################################### # Arg parsing time. There's a whole lot of different ways to pass args. # We do the standard way first. # Then duplicate everything lower down, for longopts type args while getopts "ds:uUacirhvf" mode_var ; do case $mode_var in d) mode=install downloadonly=1 ;; v) debug=1 ;; s) url=$OPTARG ;; u) mode=upgrade ;; U) mode=updatecatalog ;; a) mode=available ;; c) mode=compare ;; i) mode=install ;; r) mode=remove ;; f) force=true ;; *) usage exit 1 ;; esac done shift $(($OPTIND - 1 )) ############################################################ # This type of arg parsing is to keep some sort of compatibility # with debian "apt-get", the program that inspired pkg-get # if [[ "$mode" == "" ]] ; then case "$1" in updatecatalog|--updatecatalog) mode=updatecatalog shift ;; upgrade|--upgrade) mode=upgrade shift ;; available|--available) mode=available shift ;; compare|--compare) mode=compare shift ;; download|--download) mode=install downloadonly=1 shift ;; install|--install) mode=install shift ;; remove|--remove) mode=remove shift ;; *) mode=help esac fi ###################################################################### # End of arg-interpretation section. # Now for the action handling, after this one important check SITE=${url##*//} SITE=${SITE%%/*} # Takes the url var and parses out the value for SITE # but also makes sure url is NOT http # because we use wildcard in wget to grab package case $url in ftp://*|http://*) ;; file://*) SITE=localhost ;; *) print ERROR: right now url to the site MUST be ftp:// print $url not acceptible as source location exit 1 ;; esac CATALOGFILE=/var/pkg-get/catalog-$SITE if [[ ! -f $CATALOGFILE ]] ; then if [[ "$mode" != "update" ]] ; then print "" print WARNING: no catalog file for site $SITE print "Updating catalog file first" update_catalog fi fi # check for special override file that says, "shut up and just do it". # man -s4 admin to see the format of it, and/or see # /var/sadm/install/admin/default for the default file # # -n means "ask no questions". If you dont have the fullauto version, # perhaps you dont want the -n flag here. if [[ -f /var/pkg-get/admin ]] ; then ADMINFLAG="-a /var/pkg-get/admin" fi if [[ "$force" != "" ]] ; then ADMINFLAG="-n $ADMINFLAG" fi datecheck=`find $CATALOGFILE -mtime +30 -print 2>/dev/null` if [[ "$datecheck" != "" ]] && [[ "$mode" != "updatecatalog" ]] ; then print "WARNING: catalog out of date." print "Automatically updating catalog first" update_catalog fi PAGER=${PAGER:-more} ###################################################################### # This whole section, until the "main" routine, is a special off-shoot, # that works on CD-type distribution directories. # Assumes a bunch of directory, NOT stream, format PKGs. # Just a sneaky alias for pkginfo # Only call this if you have verified first arg is a directory dir_available(){ pkginfo -d "$1"| $PAGER } #"Directory"-package compare. # Look in an existing directory for packages, instead of downloading them # Compare installed packages, to what's in a directory # For speed reasons, we "Cheat", and do not go through the long # hasses of comparing individual pkginfo output. # First arg is directory, rest are optional pkgnames # WHICH HAVE TO BE DIRECTORY NAMES, NOT the "cute" names dir_compare(){ if [[ ! -d "$1" ]] ; then print ERROR: $1 not valid directory return fi shift # This must match up to "dir_compare_one" output. printf "%15s %15s %15s\n" "PKGNAME" "Directory-rev" "Installed-rev" if [[ $# -gt 1 ]] ; then while [[ $# -gt 1 ]] ; do dir_compare_one $1 "$1" done return fi #else for d in $1/* ; do if [[ -d "$d" ]]; then d=${d##*/} dir_compare_one $1 $d fi done } # # arg1 is a directory. arg2 is a directory name IN that directory: # MUST BE RELATIVE TO arg1!! # Will then compare pkg there, to any installed package # dir_compare_one(){ tmpdir="$1" tmppkg="$2" tmpver=`grep VERSION $tmpdir/$tmppkg/pkginfo` tmpver=${tmpver#VERSION=} tmpoldver=`grep VERSION /var/sadm/pkg/$tmppkg/pkginfo 2>/dev/null` if [[ $? -eq 0 ]] ; then tmpoldver=${tmpoldver#VERSION=} if [[ "$tmpoldver" == "$tmpver" ]] ; then tmpoldver="SAME" fi else tmpoldver="[Not installed]" fi printf "%15s %15s %15s\n" "$tmppkg" "$tmpver" "$tmpoldver" } # Given the name of a directory, install ALL packages present in # 'spool' form (directory, not a single file) # Or just install the named packages in the directory # # Remove any old versions first, IF upgrade option given dir_install(){ # we use 'DIRECTORY' as a global flag that we are installing # from a directory. Or we shall use it, someday. DIRECTORY="$1" shift if [[ $# -gt 0 ]] ; then while [[ $# -gt 0 ]] ; do dir_install_one $DIRECTORY "$1" shift done return fi #else for d in $DIRECTORY/* ; do if [[ -d "$d" ]]; then d=${d##*/} dir_install_one $DIRECTORY $d fi done } #Given the name of a directory, and the name of a pkg-directory in it, # Remove any pre-existing packages, and install the new one # # Check dependancies while we are at it. dir_install_one(){ tmpdir="$1" tmppkg="$2" if [[ -f $tmpdir/$tmppkg/install/depend ]] ; then install_dependancies $tmpdir/$tmppkg/install/depend if [ $? -ne 0 ] ; then print ERROR: could not install required dependancies for $tmppkg return 1 fi fi if [[ do_upgrade -eq 0 ]] ; then # Dont bother to upgrade, just install and get out of here. pkgadd $ADMINFLAG -d $tmpdir $tmppkg return $?; fi # otherwise, we're doing the whole nine yards. if [[ -f /var/sadm/pkg/$tmppkg ]] ; then print "Removing old version of package" pkgrm $ADMINFLAG $tmppkg fi for f in /var/sadm/pkg/${tmppkg}.* ; do if [[ -d $f ]] ; then f=${f##*/} print "Removing old instance $f" pkgrm $ADMINFLAG $f fi done pkgadd $ADMINFLAG -d $tmpdir $tmppkg } ############################################################ # And finally, the actual "main" section do_upgrade=0 case "$mode" in updatecatalog) update_catalog exit ;; upgrade) if [[ -d "$1" ]] ; then dir_install $* return fi upgrade $* exit ;; available) if [[ -d "$1" ]] ; then dir_available "$1" return fi print "# (From site $SITE)" awk '$1 ~ /^#/ {next} {printf("%20s %15s\n",$1,$2);}' $CATALOGFILE | $PAGER ;; compare) if [[ -d "$1" ]] ; then dir_compare $* return fi show_installed | $PAGER ;; install) if [[ -d "$1" ]] ; then dir_install $* return fi install_pkg $* ;; remove) remove_packages $* ;; help|*) usage esac 0707011c53d992000041ed000002bc00000001000000033cbef3c3000000000000000000000002ffffffffffffffff0000000c00000006reloc/share0707011c628d60000041ed000002bc00000001000000033cbef3c3000000000000000000000002ffffffffffffffff0000001000000006reloc/share/man0707011c628c76000041ed000002bc00000001000000023cbef3c3000000000000000000000002ffffffffffffffff0000001600000006reloc/share/man/man1m0707011c628c0e000081a4000002bc00000001000000013cbc76f9000015320000000000000002ffffffffffffffff0000002100000006reloc/share/man/man1m/pkg-get.1m.\" pkg-get.1m 2002/04/16 .TH PKG-GET 1m "April 16th, 2002" "Phil\'s Software" .SH NAME pkg-get 1.9.5 \- automatic install and upgrade of packages over the network .SH SYNOPSIS pkg-get [-d] [-s site] {-i|install} {pkgname [...]|all} pkg-get [-d] [-s site] {-u|update} [pkgname...] pkg-get [-s site] {-c|compare} | {-a|available} .SH DESCRIPTION pkg-get is similar to Debian Linux "apt-get". Its most basic use is that you tell it the name of a software package, and it automatically goes and grabs it from the net, then installs it on your system. .SH MODES .TP pkg-get updatecatalog This will 'update' a local inventory of all packages available for your system. .TP pkg-get available will show you a list of freeware packages available to install .TP pkg-get install {pkgname [pkgname...] | all} will install listed packages. If 'all' is specified, will install all packages available, at the latest version. .TP pkg-get upgrade [pkgname [pkgname...]] will automatically upgrade the listed packages to the latest version. If no arguments, will upgrade all packages that are already installed. The upgrade option will remove any older versions of packages for you. It will also automatically choose the highest revision of a package to download, if there are multiple available. .SH OPTIONS .TP -d|download Downloads the pkg file, and does NOT install. Useful if you're trying to create a local archive of pkg files .TP -v This is only meaningful for the 'install' option, without arguments. It adds "verbose" mode, to tell you what would be upgraded. BUT... it stops the program actually downloading any newer files! .TP -i|install [softwarename] Looks through all packages you have installs, and compares them to the latest available on the site. If the site has newer versions, it will download and install all newer versions of software you already have. It will NOT install packages you do not already have installed. If you specify a particular software name, it will first look up the specific software name in the local contents cache. If you already have the same version installed, says so and quits. Otherwise, if it is available, pkg-get will download and install it. .TP -U|updatecatalog Updates the local cache of the special "contents" file from the freeware site. All "compare versions" operations are done on the locally cached copy. pkg-get will automatically update the catalog if it is older than a month. .TP -u|upgrade Attempts to upgrade any installed packages that have newer versions available on the site. .TP -a|available This just prints out the software name and revision of all packages available for download. In a future version, it may also print out descriptions of each package. .TP -c|compare Display a comparision of versions between installed packages, and what is available on the site. If you do not have a package installed, it will show "not installed" for the local version stamp. .TP -f Force default action on pkg add or remove; Dont ask questions. This may mean that it will refuse to install some packages, depending on what the pkgadd defaults are, whether there are conflicts, etc. The 'normal' defaults are specified in /var/sadm/install/admin/default. See the "MORE AUTOMATION" section at the bottom of this manpage. .TP -r|remove This option was added by request. However, it is inherently not as bulletproof as the other options, because nothing in the site catalog says that the pkg version and the software version have to match. However, it should work as expected 95% of the time. And worst case, it will ONLY remove packages that are on the remote site catalog; It should not remove Solaris packages. .SH PROXIES See /etc/pkg-get.conf for comments on how to use wget behind a proxy. Basically, just export the environment variables http_proxy and ftp_proxy. The conf file lets you do that without messing with users' environments directly. .SH MORE AUTOMATION If you dont like answering pkgadd prompts, you can create an 'admin' file, as /var/pkg-get/admin A sample 100% hands-off admin file is provided, as /var/pkg-get/admin-fullauto. It will no longer give you warnings about setuid installscripts, conflicts, and other issues. However, it may still ask you in some instances, "Do you want to install/remove this package", unless you use the -f option to pkg-get. Contrariwise, if you use -f without overriding the defaults, pkg-get will not install a non-trivial amount of packages. For full details of the format of the admin file, man -s4 admin. .SH FILES /etc/pkg-get.conf /var/pkg-get/catalog-sitename /var/pkg-get/admin /var/pkg-get/admin-fullauto .SH BUGS I wouldn't be surprised if there are one or two bugs to be worked out. If so, please email me about them! Also, this was designed to only keep track of packages made by sunfreeware. If you get a package of gcc from elsewhere (eg: the "bonus software" package with solaris 8) the name of the pkg will probably be different (SMCgcc, vs SFWgcc, for example) . So when it says you dont have gcc installed, what it really means is, "you dont have SunFreeware-packaged gcc installed" .SH SEE ALSO If you are interested in setting up your own local freeware server, http://www.bolthole.com/solaris/makecontents is the tool needed to automatically generate the catalog for each directory. .SH AUTHOR Philip Brown phil@bolthole.com http://www.bolthole.com/solaris/ 0707011c5eb275000041ed000002bc00000001000000033cbef3c3000000000000000000000002ffffffffffffffff0000000500000006root0707011c282a83000041ed000002bc00000001000000033cbef3c3000000000000000000000002ffffffffffffffff0000000900000006root/var0707011c7689c9000041ed000002bc00000001000000023cbef3c3000000000000000000000002ffffffffffffffff0000001100000006root/var/pkg-get0707011c628d2c000081a4000002bc00000001000000013c92f794000001d40000000000000002ffffffffffffffff0000002000000006root/var/pkg-get/admin-fullauto# Sample 'admin' file, to change the behaviour of pkg-get # If you copy this file to /var/pkg-get/admin, it will use it # to override the system defaults set in /var/sadm/install/admin/default # If you use this override file, be 100% sure you trust the source # of packages that you point pkg-get to. mail= instance=overwrite partial=nocheck runlevel=nocheck idepend=nocheck rdepend=nocheck space=nocheck setuid=nocheck conflict=nocheck action=nocheck basedir=default 07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000b00000000TRAILER!!!