#!/bin/sh # protopkg - Slackware .tgz Packaging Tool # # Written by David Cantrell, licensed under the GPL (any version). # Copyright 2000, BSDi, Concord, California, USA. # All rights reserved. # # Portions were taken from the "hdsetup" tools in Slackware Linux: # # Copyright 1994, 1998 Patrick Volkerding, Moorhead, Minnesota USA # All rights reserved. # # Redistribution and use of this script, with or without modification, is # permitted provided that the following conditions are met: # # 1. Redistributions of this script must retain the above copyright # notice, this list of conditions and the following disclaimer. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # Standard Defines # alias tar=tar-1.13 # version number VER="2.0" # extension for Slackware packages PKG_EXTENSION=tgz # package rules file name PKG_RULES=rules # the default editor that protopkg uses to verify the package listing EDITOR=/usr/bin/vi # general temp directory if [ "$TMP" = "" ] then TMP=/tmp fi # # afterinstall() # Called by protopkg() after the install function from the package # prototype file is run. Generates a listing of all files on the system, # compares against what beforeinstall() found and from that generates a # list of files that go in the package. Neat, huh? # afterinstall() { cd $TMP find / $IPATH -printf "%p ! %T@ ! %s\n" > $TMP/after.lst cat before.lst after.lst | sort | uniq -u > $TMP/package.lst # in the case that the destination stuff existed, eliminate duplicates cat package.lst | cut -d'!' -f1 | sed -e 's% *$%%' | uniq | grep -v "usr/info/dir" | grep -v usr/local/info/dir > $TMP/package.new rm -f package.lst ; mv package.new package.lst # remove the before and after lists, since we don't need them anymore rm -rf $TMP/before.lst rm -rf $TMP/after.lst } # # beforeinstall() # Called by protopkg() before the install function from the package # prototype file is run. Makes a list of files on the system that # afterinstall() will read later. # beforeinstall() { rm -f $TMP/before.lst find / $IPATH -printf "%p ! %T@ ! %s\n" > $TMP/before.lst } # # build_package() # Called by protopkg() after afterinstall() has been run. It takes the # list of files that go in the package and tars them up. It then moves to # the temporary package build directory and untars those files there. # This is done so that permissions and such can be fixed up on the package # contents. # # Parameters: $1 The package name # $2 The package tree # build_package() { cd $TMP mkdir -p $2 chown root.root $2 chmod 755 $2 (set -o noglob IFS=" " for hejaz in `cat $TMP/package.lst` do if [ ! "`file $hejaz | grep \"symbolic link\"`" = "" ] then # we want symbolic links echo $hejaz >> $TMP/archive.lst elif [ ! "`file $hejaz | grep \"directory\$\"`" = "" -a ! -f $hejaz ] then # empty directories get caught for later creation echo $hejaz >> $TMP/emptydirs.lst elif [ ! -d $hejaz ] then # catch all other files echo $hejaz >> $TMP/archive.lst fi done set +o noglob) rm -rf $TMP/package.lst # create the package tree cd $2 if [ "$VERBOSE" = "y" ] then tar -cvf - -T $TMP/archive.lst | tar -xf - else tar -cvf - -T $TMP/archive.lst | tar -xf - 1>/dev/null 2>/dev/null fi # run through our directory list and make that in the tree if [ "x$SUBPKG" = "x" ]; then DIR=$PKG else DIR=$SUBPKG fi for d in `cat $TMP/emptydirs.lst` do tmpD=`trim_slash $d` if [ ! -d $DIR/$tmpD ] then mkdir -p $DIR/$tmpD fi done rm -rf $TMP/emptydirs.lst rm -rf $TMP/archive.lst } # # compressdocs() # Compresses all man pages and info files in a package tree. # # Parameters: $1 The package tree. # compressdocs() { dir1=`pwd` cd $1 for dn in usr \ usr/local \ 'opt/*' \ usr/X11R6 \ usr/openwin do # adapted by Jasper Huijsmans to repair broken links # and to also gzip the originally installed file for dn2 in man share/man info share/info do for file in `find $dn/$dn2 -type f 2>/dev/null` do gzip -9f $1/$file /$file 2>/dev/null done for link in `find $dn/$dn2 -type l 2>/dev/null` do relink_docs $1/$link 2>/dev/null relink_docs /$link 2>/dev/null done done done cd $dir1 } # # doinst_rules() # Adds doinst.sh code for removing additional control files, installing # info files, and handling the config file "rules" file. # # Parameters: $1 The package tree. # $2 The control directory in the package tree. # doinst_rules() { # handle any info files that are in the package tree cd $1 noIf=y for dn in usr \ usr/local \ opt \ usr/X11R6 \ usr/openwin do # find unique info files in the directory for infof in `find $1/$dn/info -type f -print 2>/dev/null | \ grep -v -e '.*-[0-9]\+\.gz'` do if [ "$noIf" = "y" ] then ( cd $1/install echo "# Install the info files for this package" >> doinst.sh echo "if [ -x usr/bin/install-info ]" >> doinst.sh echo "then" >> doinst.sh ) noIf=n fi echo " usr/bin/install-info --info-dir=/$dn/info /$dn/info/`basename $infof` 2>/dev/null" >> $1/install/doinst.sh done done # close the installer block if [ "$noIf" = "n" ] then ( cd $1/install echo "fi" >> doinst.sh echo >> doinst.sh ) fi # handle any config files in the config file processing dir if [ -d $1/install/conf ] then ( cd $1/install echo "# Process the incoming configuration files" >> doinst.sh ) cat $CWD/rules | read_rules "conf" | ( while read Caction Cfile do if [ "$Cfile" = "" ] then ### This is the default installation method realF=`trim_slash $Caction` ( cd $1/install echo >> doinst.sh cat << EOF >> doinst.sh if [ ! -f $realF ] then mv install/conf/$realF $realF else if [ "\`md5sum install/conf/$realF | cut -d ' ' -f 1 2>/dev/null\`" = "\`md5sum $realF | cut -d ' ' -f 1 2>/dev/null\`" ] then mv install/conf/$realF $realF else mv install/conf/$realF $realF.new fi fi EOF ) elif [ "$Caction" = "ONE" ] then ### Handle the ONE installation mode realF=`trim_slash $Cfile` ( cd $1/install echo >> doinst.sh cat << EOF >> doinst.sh if [ ! -f $realF ] then mv install/conf/$realF $realF else if [ "\`md5sum install/conf/$realF | cut -d ' ' -f 1 2>/dev/null\`" = "\`md5sum $realF | cut -d ' ' -f 1 2>/dev/null\`" ] then mv install/conf/$realF $realF else rm install/conf/$realF fi fi EOF ) else ### We need to handle the other modes realF=`trim_slash $Cfile` if [ "$Caction" = "NEW" ] then destF="$realF.new" elif [ "$Caction" = "EXAMPLE" ] then destF="$realF.example" elif [ "$Caction" = "OW" ] then destF=$realF fi ( cd $1/install echo >> doinst.sh echo "mv install/conf/$realF $destF" >> doinst.sh ) fi done ) ( cd $1/install echo >> doinst.sh echo "# Make sure the incoming conf directory is gone" >> doinst.sh echo "rm -rf install/conf" >> doinst.sh ) fi } # # download_sources() - If the source code has not been downloaded and we have # a sources file, try to fetch the source. If the source is downloaded and # can be verified, do that and exit. # # Parameters: $1 The name of the sources file. # download_sources() { # find a suitable download tool if [ -x `which wget` ] then DWNLDTOOL="`which wget`" elif [ -x `which lynx` ] then DWNLDTOOL="`which lynx` -source" else echo echo "You lack a sufficient download tool for protopkg. Make sure" echo "that either wget or lynx is installed, both of which are in" echo "Slackware in the networking series." echo exit fi # let's do it cat $1 | read_rules "sources" | ( while read Surl Smd5 do Sfile="`basename $Surl`" GOOD="n" # do we have the file already? if [ -f $Sfile ] then # we have the file, does it check out? if [ ! "$Smd5" = "" ] then oldSum="`md5sum $Sfile`" oldSum="`echo $oldSum | cut -d ' ' -f 1`" if [ "$oldSum" = "$Smd5" ] then GOOD="y" else GOOD="n" fi else # we can't verify the MD5 sig, assume good GOOD="y" fi fi # let's fetch if [ "$GOOD" = "n" ] then $DWNLDTOOL $Surl if [ ! "$Smd5" = "" ] then # verify the MD5 sig newSum="`md5sum $Sfile`" newSum="`echo $newSum | cut -d ' ' -f 1`" if [ ! "$newSum" = "$Smd5" ] then echo "$Sfile is invalid!" mv $Sfile $Sfile.invalid fi fi fi done ) unset Surl Smd5 Sfile GOOD } # # filesize() # This function duplicates what the "filesize" program in Slackware does. # We may not have this on the particular filesystem we're on. It's # simple enough to just be a function. # # The argument it accepts is a filename to take the size of. # file_size() { SIZE=`ls -l -d -G "$1" | cut -b23-32` echo -n $SIZE } # # fixate_package() # Called by protopkg() to actually create the final package. It packages # up the contents of the temporary package build directory. # # Parameters: $1 The package name. # $2 The package tree. # $3 The embedded package control directory. # fixate_package() { cd $2 # first, warn for any zero-length files that may be unintentional find . -type f -size 0c | while read file do echo "WARNING: zero length file $file" done find . -type f -name '*.gz' -size 20c | while read file do echo "WARNING: possible empty gzipped file $file" done # Add more useful stuff to the doinst.sh script doinst_rules $2 $3 # if the control directory is still empty, remove it. --lj rmdir $3 1>/dev/null 2>/dev/null # now, create the actual package if [ "$VERBOSE" = "y" ] then echo tar -cvf $CWD/$1.tar . gzip -9 $CWD/$1.tar mv $CWD/$1.tar.gz $CWD/$1.tgz else tar -cvf $CWD/$1.tar . 2>/dev/null 1>/dev/null gzip -9 $CWD/$1.tar 2>/dev/null 1>/dev/null mv $CWD/$1.tar.gz $CWD/$1.tgz 2>/dev/null 1>/dev/null fi # Generate a package_descriptions file if the user wants that if [ "$CREATE_DESCRIPTION" = "y" -a ! "$DESC" = "" ] then echo >> $CWD/package_descriptions # output the package name first for a in 1 2 3 4 5 6 7 8 9 10 11 do echo "$PKGNAME:" >> $TMP/leftside done # now place the description in a file echo -e "$DESC" > $TMP/rightside # combine the two paste -d ' ' $TMP/leftside $TMP/rightside >> $CWD/package_descriptions echo >> $CWD/package_descriptions rm -rf $TMP/leftside $TMP/rightside fi } # # make_install_script() # Runs through the temporary package directory and searches for symlinks. # These are put into a script to create those symlinks at installation # time. # make_install_script() { sed -e 's% -> %!%' -e 's% %\\ %g' $1 > $1.new && mv $1.new $1 COUNT=1 LINE="`sed -n "$COUNT p" $1`" while [ ! "$LINE" = "" ] do LINKGOESIN="`echo "$LINE" | cut -f 1 -d "!"`" LINKGOESIN="`dirname "$LINKGOESIN"`" LINKNAMEIS="`echo "$LINE" | cut -f 1 -d '!'`" LINKNAMEIS="`basename "$LINKNAMEIS"`" LINKPOINTSTO="`echo "$LINE" | cut -f 2 -d '!'`" echo "( cd $LINKGOESIN ; rm -rf $LINKNAMEIS )" echo "( cd $LINKGOESIN ; ln -sf $LINKPOINTSTO $LINKNAMEIS )" COUNT=`expr $COUNT + 1` LINE="`sed -n "$COUNT p" $1`" done } # # permissionize() # Called by protopkg() to fix permissions on the temporary package build # directory. It sets all bin and sbin stuff to root.bin, chmod'ed 755. # After that it runs the ownerships and permissions functions from the # package prototype file (to set any special permissions the package # maintainer wants). # # Parameters: $1 The package tree. # permissionize() { cd $1 if [ ! "$SETATTR" = "n" ] then # default system-wide permissions find . -exec chown root.root {} \; 1>/dev/null 2>/dev/null find . -type d -exec chmod 755 {} \; 1>/dev/null 2>/dev/null find . -type d -exec chown root.root {} \; 1>/dev/null 2>/dev/null # default bin and sbin permissions (root.bin, 755) for d in usr/bin usr/sbin usr/X11R6/bin bin sbin usr/local/bin usr/local/sbin do chown -R root.bin $1/$d 2>/dev/null chmod -R 755 $1/$d 2>/dev/null done # default include permissions find usr/include -name *.h -exec chmod 644 {} \; 1>/dev/null 2>/dev/null find usr/X11R6/include -name *.h -exec chmod 644 {} \; 1>/dev/null 2>/dev/null # default man and info page permissions find usr/man -type f -exec chmod 644 {} \; 1>/dev/null 2>/dev/null find usr/X11R6/man -type f -exec chmod 644 {} \; 1>/dev/null 2>/dev/null find usr/info -type f -exec chmod 644 {} \; 1>/dev/null 2>/dev/null # default /usr/doc permissions and ownerships find . | grep "usr/doc" | xargs chown root.root 1>/dev/null 2>/dev/null find . -type f | grep "usr/doc" | xargs chmod 644 1>/dev/null 2>/dev/null find . -type d | grep "usr/doc" | xargs chmod 755 1>/dev/null 2>/dev/null fi # run the user-defined functions if [ ! "$SUBPKGNAME" = "" ] then ### we're in a subpackage, a la repack() subattributes 2>/dev/null 1>/dev/null else ### looks like a regular ol' package to me attributes 2>/dev/null 1>/dev/null fi } # # prepare_conf() # Called by protopkg to move the config files specified in the rules file # to the CONF processing directory. # # Parameters: $1 The subpackage name (leave empty for main package) # prepare_conf() { # get the full path to the rules file if [ "$1" = "" ] then rulesFile="$CWD/rules" confDir="$CTL/conf" pkgRoot="$PKG" else rulesFile="$CWD/rules.$1" confDir="$SUBCTL/conf" pkgRoot="$SUBPKG" fi # let's do it if [ -f $rulesFile ] then cat $rulesFile | read_rules "conf" | ( while read Caction Cfile do # get the file to put in the conf processing dir if [ "$Cfile" = "" ] then copyFile=$Caction else copyFile=$Cfile fi # move the file echo " --> $copyFile" mkdir -p "$confDir/`dirname $copyFile`" mv $pkgRoot/$copyFile $confDir/$copyFile done ) unset Caction Cfile pkgRoot copyFile confDir fi } # # read_rules # Reads the specified rules file for the specified block. # # Parameters: $1 The block name to search for. # read_rules() { sed -e '/^#/d' -e '/^$/d' | sed -n "/^${1}:/,/^:${1}$/p" | grep -Fv "${1}:" | grep -Fv ":${1}" | sed -e "s/^[ \t]*//" } # # relink_docs() # repair broken links to docs cause by gzipping # added by Jasper Huijsmans # # Parameters: $1 The symbolic link file # relink_docs() { LINKGOESIN=`dirname $1` LINKNAMEIS=`basename $1` LINKPOINTSTO=`ls -l $1 | cut -b59- | cut -f 3 -d ' '` rm $1 # Here comes the trick: just add .gz to every name ( cd $LINKGOESIN; ln -s $LINKPOINTSTO.gz $LINKNAMEIS.gz ) } # # repack() # This is a function called by prototype files when one source tree # builds multiple binary packages. # repack() { # $1 is our subpackage name to create if [ "$1" = "" ] then echo "ERROR: Subpackage name not specified for repack() call." else ### the way repack works is similar to protopkg. it inherits certain ### pieces of information from the main prototype, but has it's own ### as well. it's kinda hard to follow (especially at 5:43AM), so ### pay close attention. -David # look for a subproto if [ ! -f $CWD/prototype.$1 ] then echo "ERROR: Aborting repack(), prototype.$1 not found." return else . $CWD/prototype.$1 fi echo echo "Building subpackage $1..." echo ### VERIFY SUBPROTOTYPE FILE echo -n "Verifying subpackage prototype file..." verifyproto "sub" "$1" echo "good, building package [$SUBPKGNAME]" ### FETCH SOURCE CODE IF WE NEED TO if [ -f $CWD/sources.$1 ] then echo -n "Fetching source code..." cd $CWD if [ "$VERBOSE" = "y" ] then echo download_sources $CWD/sources.$1 else download_sources $CWD/sources.$1 2>/dev/null 1>/dev/null echo "done." fi fi ### DO WE NEED TO COMPILE? if [ ! "$COMPILED" = "y" ] then echo -n "Compiling package [$PKGNAME]..." cd $TMP if [ "$VERBOSE" = "y" ] then echo compile else compile 2>/dev/null 1>/dev/null echo "done." fi COMPILED=y fi ### BUILD LIST OF INSTALLED FILES echo -n "Generating list of files for subpackage [$SUBPKGNAME]..." beforeinstall if [ "$VERBOSE" = "y" ] then echo subinstall else subinstall 2>/dev/null 1>/dev/null fi afterinstall if [ ! "$VERBOSE" = "y" ] then echo "done." fi ### HAVE USER PLAY WITH PACKAGE LIST UNLESS BATCH MODE IS SET if [ ! "$BATCH" = "y" ] then cat << EOF protopkg has gathered a list of what it things should be in the subpackage. You will now be given the opportunity to edit that list if you see that protopkg missed anything or got something wrong. Just type in the editor you want to use and hit enter to edit the package list. After you exit the editor, protopkg will finish making the subpackage. EOF echo -n "Editor to use [default: $EDITOR]: " read usered if [ "$usered" = "" ] then $EDITOR $TMP/package.lst else if [ ! -x $usered -a ! -f $usered ] then echo echo "Error with editor specified, defaulting to $EDITOR" $EDITOR $TMP/package.lst else $usered $TMP/package.lst fi fi fi echo ### SET THE SUBPACKAGE AND SUBPACKAGE CONTROL VARIABLES SUBPKG=$TMP/pkg-$SUBPKGNAME SUBCTL=$SUBPKG/install if [ "$VERBOSE" = "y" ] then echo "Creating subpackage tree..." build_package $SUBPKGNAME $SUBPKG stripeverything $SUBPKG restoredoctimes $SUBPKGNAME $SUBPKG permissionize $SUBPKG compressdocs $SUBPKG else echo -n "Creating subpackage tree..." build_package $SUBPKGNAME $SUBPKG 2>/dev/null 1>/dev/null stripeverything $SUBPKG 2>/dev/null 1>/dev/null restoredoctimes $SUBPKGNAME $SUBPKG 2>/dev/null 1>/dev/null permissionize $SUBPKG 2>/dev/null 1>/dev/null compressdocs $SUBPKG 2>/dev/null 1>/dev/null fi if [ ! "$VERBOSE" = "y" ] then echo "done." fi ### CHECK FOR ZERO-LENGTH FILES if [ "$VERBOSE" = "y" ] then echo "Checking for zero-length files..." fi zerocheck $SUBPKG ### MAKE THE SYMLINKS FOR THE DOINST if [ "$VERBOSE" = "y" ] then symlinks $SUBPKG $SUBCTL else symlinks $SUBPKG $SUBCTL 2>/dev/null 1>/dev/null fi ### RUN THE SPECIAL FUNCTION cd $SUBPKG if [ "$VERBOSE" = "y" ] then subspecial else subspecial 2>/dev/null 1>/dev/null fi ### READ THE RULES FILE AND PREPARE INCOMING CONFIG FILES if [ "$VERBOSE" = "y" ] then echo "Preparing incoming configuration files for processing..." prepare_conf $SUBPKGNAME else prepare_conf $SUBPKGNAME 2>/dev/null 1>/dev/null fi ### FIXATE PACKAGE if [ "$VERBOSE" = "y" ] then echo "Fixating package [$SUBPKGNAME]..." else echo -n "Fixating package [$SUBPKGNAME]..." fi fixate_package $SUBPKGNAME $SUBPKG $SUBCTL if [ ! "$VERBOSE" = "y" ] then echo "done." fi echo fi } # # restoredoctimes() # Restore original timestamps for files in the /usr/doc directory. This # is part of the package design for all Slackware packages. It's policy # to maintain original timestamps for documentation. # # Parameters: $1 The package name. # $2 The package tree. # restoredoctimes() { echo echo "Restoring original timestamps on /usr/doc files..." # get a list of files that fall into /usr/doc rm -rf $TMP/doc-$1 mkdir -p $TMP/doc-$1 find $2 -type f -print | grep "usr/doc" > $TMP/doc-$1/installed.lst # make a list of original files for each basename that got installed for installed in `cat $TMP/doc-$1/installed.lst` do find $TMP -type f -name `basename $installed` -print | \ grep -v pkg-$1 >> \ $TMP/doc-$1/`basename $installed`.orig.lst done # remove any lists that only consist of one file; messing with those # would just slow us down. for list in `find $TMP/doc-$1 -type f` do lines=`grep -c \$ $list` if [ $lines -eq 1 ] then rm -f $list fi done # loop of doom loop. # # for every file that got installed (in our installed.lst), do the # following: # 1) see if there is a corresponding basename.orig.lst # 1a) if not, that means there's only one file in $TMP with the same # basename do a find in TMP and cp -a whatever turns up. # 1b) if so, loop through basename.orig.lst, comparing md5sums, until a # match is found. cp -a the matching file; all others are being # written out to basename.orig.lst.checked, which is moved back to # basename.orig.lst when done (thus eliminating matched file from # list to be checked in the future) # 3) rinse, repeat. for installed in `cat $TMP/doc-$1/installed.lst` do base=`basename $installed` if [ ! -f "$TMP/doc-$1/$base.orig.lst" ] then original=$(find $TMP -type f -name `basename $installed` -print | \ grep -v pkg-$1) if [ "$VERBOSE" = "y" ] then # remove the TMP and PKG directory from the path tmpStart=`expr length $2` tmpStart=`expr $tmpStart + 1` tmpVar=$(expr substr $installed $tmpStart `expr length $installed`) # display the file we restored echo " --> $tmpVar" # reclaim memory...maybe?...it's not exactly free() :) unset tmpVar tmpStart fi # We're now just touching files with the correct stamp instead of # recopying the file with cp -a #cp -a $original $installed touch -r $original $installed else installed_md5sum=`md5sum $installed | cut -d' ' -f1` nf=1 for original in `cat $TMP/doc-$1/$base.orig.lst` do if [ "$nf" -a \ "$installed_md5sum" = "`md5sum $original | cut -d' ' -f1`" ] then unset nf # We're now just touching files with the correct stamp instead # of recopying the file with cp -a #cp -a $original $installed touch -r $original $installed else echo "$original" >> $TMP/doc-$1/$base.orig.lst.checked fi done mv $TMP/doc-$1/$base.orig.lst.checked \ $TMP/doc-$1/$base.orig.lst fi done echo } # # stripeverything() # Goes through the package tree and strips all ELF stuff (binaries, # libraries, and so on). # # Parameters: $1 The package tree. # stripeverything() { cd $1 STATIC_DONE=n # strip shared libraries and binaries if [ ! "$STRIPLIB" = "n" -o ! "$STRIPBIN" = "n" ] then msgOut=n for testname in `find . -type f` do islib="`file $testname | grep ELF | \ grep 'shared object' | \ grep 'not stripped'`" isprog="`file $testname | grep ELF | \ grep executable | \ grep 'not stripped'`" isstatic="`file $testname | grep 'current ar archive'`" # strip binaries if the user so desires if [ ! "$isprog" = "" -a "$STRIPBIN" = "y" ] then if [ "$msgOut" = "n" ] then echo echo "Stripping ELF objects, generating static library indexes..." msgOut=y fi echo " --> strip -p $testname" strip -p $testname 2>/dev/null 1>/dev/null fi # strip libraries if the user so desires if [ ! "$islib" = "" -a "$STRIPLIB" = "y" ] then if [ "$msgOut" = "n" ] then echo echo "Stripping ELF objects, generating static library indexes..." msgOut=y fi echo " --> strip -p $testname" strip -p $testname 2>/dev/null 1>/dev/null fi # run ranlib on static libraries if [ ! "$isstatic" = "" ] then STATIC_DONE=y echo " --> ranlib $testname" ranlib $testname 2>/dev/null 1>/dev/null fi done if [ "$msgOut" = "y" ] then echo fi fi if [ "$STATIC_DONE" = "n" ] then # ranlib static libraries msgOut=n for libname in `find . -name *.a -type f` do if [ ! "`file $libname | grep 'current ar archive'`" = "" ] then if [ "$msgOut" = "n" ] then echo echo "Generating static library indexes..." msgOut=y fi echo " --> $libname" ranlib $libname 2>/dev/null 1>/dev/null fi done fi } # # symlinks() # Called by protopkg() to remove any symlinks found in the temporary # package build directory. Also makes the doinst.sh file for recreating # those at install time. # # Parameters: $1 The package tree. # $2 The embedded package control directory. # symlinks() { # Get rid of possible pre-existing trouble: rm -rf $TMP/iNsT-a.$$ cd $1 if [ "$VERBOSE" = "y" ] then echo find . -type l -ls | cut -b70- | tee $TMP/iNsT-a.$$ else find . -type l -ls | cut -b70- > $TMP/iNsT-a.$$ fi cd $TMP # create the install directory if we need it if [ ! -d $2 ] then mkdir -p $2 chown root.root $2 chmod 755 $2 fi if [ ! "`file_size $TMP/iNsT-a.$$`" = "0" ] then if [ "$VERBOSE" = "y" ] then echo make_install_script $TMP/iNsT-a.$$ | tee $TMP/doinst.sh else make_install_script $TMP/iNsT-a.$$ > $TMP/doinst.sh fi # write out the doinst script cat $TMP/doinst.sh >> $2/doinst.sh chown root.root $2/doinst.sh chmod 644 $2/doinst.sh # remove symlinks and clean up temp files cd $1 if [ "$VERBOSE" = "y" ] then echo find . -type l -exec rm -v {} \; else find . -type l -exec rm {} \; fi cd $TMP ; rm -f doinst.sh iNsT-a.$$ fi rm -rf $TMP/iNsT-a.$$ } # # trim_slash() # Removes the first character of the passed in string if it's a slash. # trim_slash() { if [ "`echo $1 | cut -c1`" = "/" ] then expr substr $1 2 `expr length $1` fi } # # verifyproto() # Called by protopkg() after it finds a prototype file. It checks to make # sure you have a compile and install functions, as well as a PKGNAME # variable. Those are the minimum things needed to create a package. # verifyproto() { # checks to make sure the prototype file is good to go if [ ! "$1" = "sub" ] then SECT_INSTALL="`cat ./prototype | grep install\(\)`" SECT_COMPILE="`cat ./prototype | grep compile\(\)`" SECT_PKGNAME="`cat ./prototype | grep PKGNAME=`" else ### checking a subpackage prototype file SECT_INSTALL="`cat $CWD/prototype.$2 | grep subinstall\(\)`" SECT_COMPILE="hejaz" SECT_PKGNAME="`cat $CWD/prototype.$2 | grep SUBPKGNAME=`" fi if [ "$SECT_INSTALL" = "" ] then echo "BAD" if [ "$1" = "sub" ] then echo "You are missing the subinstall() section from your subprototype file." else echo "You are missing the install() section from your prototype file." fi exit fi if [ "$SECT_COMPILE" = "" ] then echo "BAD" echo "You are missing the compile() section from your prototype file." exit fi if [ "$SECT_PKGNAME" = "" ] then echo "BAD" if [ "$1" = "sub" ] then echo "You are missing the package name (SUBPKGNAME) from your subprototype file." else echo "You are missing the package name (PKGNAME) from your prototype file." fi exit fi } # # zerocheck() # Called by protopkg() to check for possible zero-length files that are in # the package. This usually indicates an error in the compile process. # # Parameters: $1 The package tree. # zerocheck() { cd $1 find . -type f -size 0c | while read file ; do echo " WARNING: zero length file $file" done find . -type f -name '*.gz' -size 20c | while read file ; do echo " WARNING: possible empty gzipped file $file" done } # # protopkg_help() # protopkg_help() { cat << EOF protopkg $VER Create a new Slackware Linux software package. Usage: `basename $0` [options] Options: -v, --verbose Verbose mode. -c, --cleanup Remove build tree after package is made. -b, --batch Batch mode, do not present list of found files. -p, --package Only build the specified subpackage. If is null, only build the main package. -r, --remove Remove the source archives after building. -d, --description Generate a package description file for the package(s) that are created. -h, --help Display the help screen. EOF } # # protopkg() # Main function for the protopkg operation. Reads in a ./prototype file, # verifies it, and uses it to make a valid package. # protopkg() { # look for a prototype file if [ ! -f ./prototype ] then echo "ERROR: No package prototype file found." exit else . ./prototype fi # common variables TMP=$TMP/build-${PKGNAME} CWD=`pwd` COMPILED=n if [ ! -d $TMP ] then mkdir -p $TMP chmod 700 $TMP fi # set the ignore path IPATH="-path /proc -prune -o" if [ "$IGNOREPATH" != "" ] then IGNOREPATH="`echo $IGNOREPATH | sed -e s/\:/\ \-prune\ \-o\ \-path\ /g`" IPATH="$IPATH -path $IGNOREPATH -prune -o" fi echo "protopkg - version $VER" echo ### VERIFY PACKAGE PROTOTYPE FILE echo -n "Verifying package prototype file..." verifyproto echo "good, building package [$PKGNAME]" echo # are we only building one subpackage? if [ ! "$BUILD_SUBPACK" = "" ] then repack $BUILD_SUBPACK echo -n "Cleaning up temporary files..." if [ "$CLEANUP" = "y" ] then cd / rm -rf $TMP 2>/dev/null 1>/dev/null echo "done." else echo "skipping." fi exit fi ### FETCH SOURCE CODE IF WE NEED TO if [ -f $CWD/sources ] then echo -n "Fetching source code..." cd $CWD if [ "$VERBOSE" = "y" ] then echo download_sources $CWD/sources else download_sources $CWD/sources 2>/dev/null 1>/dev/null echo "done." fi fi ### COMPILE PROGRAM echo -n "Compiling package [$PKGNAME]..." cd $TMP if [ "$VERBOSE" = "y" ] then echo compile else compile 2>/dev/null 1>/dev/null echo "done." fi COMPILED=y ### BUILD LIST OF INSTALLED FILES echo echo -n "Generating list of files for package [$PKGNAME]..." beforeinstall if [ "$VERBOSE" = "y" ] then echo install else install 2>/dev/null 1>/dev/null fi afterinstall if [ ! "$VERBOSE" = "y" ] then echo "done." fi ### HAVE USER PLAY WITH PACKAGE LIST UNLESS BATCH MODE IS SET if [ ! "$BATCH" = "y" ] then cat << EOF protopkg has gathered a list of what it thinks should be in the package. You will now be given the opportunity to edit that list if you see that protopkg missed anything or got something wrong. Just type in the editor you want to use and hit enter to edit the package list. After you exit the editor, protopkg will finish making the package. EOF echo -n "Editor to use [default: $EDITOR]: " read usered if [ "$usered" = "" ] then $EDITOR $TMP/package.lst else if [ ! -x $usered -a ! -f $usered ] then echo echo "Error with editor specified, defaulting to $EDITOR" $EDITOR $TMP/package.lst else $usered $TMP/package.lst fi fi fi echo ### Set the package and package control variables PKG=$TMP/pkg-$PKGNAME CTL=$PKG/install if [ "$VERBOSE" = "y" ] then echo "Creating package tree..." build_package $PKGNAME $PKG stripeverything $PKG restoredoctimes $PKGNAME $PKG permissionize $PKG compressdocs $PKG else echo -n "Creating package tree..." build_package $PKGNAME $PKG 2>/dev/null 1>/dev/null stripeverything $PKG 2>/dev/null 1>/dev/null restoredoctimes $PKGNAME $PKG 2>/dev/null 1>/dev/null permissionize $PKG 2>/dev/null 1>/dev/null compressdocs $PKG 2>/dev/null 1>/dev/null fi if [ ! "$VERBOSE" = "y" ] then echo "done." fi ### CHECK FOR ZERO-LENGTH FILES if [ "$VERBOSE" = "y" ] then echo "Checking for zero-length files..." fi zerocheck $PKG echo ### MAKE THE SYMLINKS FOR THE DOINST if [ "$VERBOSE" = "y" ] then symlinks $PKG $CTL else symlinks $PKG $CTL 2>/dev/null 1>/dev/null fi ### RUN THE SPECIAL FUNCTION cd $PKG if [ "$VERBOSE" = "y" ] then special else special 2>/dev/null 1>/dev/null fi ### READ THE RULES FILE AND PREPARE INCOMING CONFIG FILES if [ "$VERBOSE" = "y" ] then echo "Preparing incoming configuration files for processing..." prepare_conf else prepare_conf 2>/dev/null 1>/dev/null fi ### FIXATE PACKAGE if [ "$VERBOSE" = "y" ] then echo "Fixating package [$PKGNAME]..." else echo -n "Fixating package [$PKGNAME]..." fi fixate_package $PKGNAME $PKG $CTL if [ ! "$VERBOSE" = "y" ] then echo "done." fi ### HANDLE ANY SUBPACKAGES if [ ! "$SKIP_SUBPACKS" = "y" ] then if [ "$VERBOSE" = "y" ] then echo echo "Building subpackages..." subpacks else echo -n "Building subpackages..." subpacks 2>/dev/null 1>/dev/null echo "done." fi fi ### REMOVE SOURCE ARCHIVES IF WE NEED TO if [ "$REMOVE_SOURCES" = "y" ] then for f in `/bin/ls -1 $CWD/sources*` do cat $f | read_rules "sources" | ( while read Surl Smd5 do Sfile="`basename $Surl`" rm -rf $CWD/$Sfile 2>/dev/null 1>/dev/null done ) unset Sfile Surl Smd5 done fi ### CLEANUP echo echo -n "Cleaning up temporary files..." if [ "$CLEANUP" = "y" ] then cd / rm -rf $TMP 2>/dev/null 1>/dev/null echo "done." else echo "skipping." fi } ### ### PROTOPKG ### # parse the command line options CL=`getopt -o vcbp::rdh --long verbose,cleanup,batch,package::,remove,description,help -- "$@"` # no options, show the help screen and terminate if [ ! $? = 0 ] then protopkg_help exit fi # set the parsed options to be our new positional parameter list eval set -- "$CL" # evaluate the command line options for OPT in $@ do case $OPT in "-v"|"--verbose") VERBOSE=y shift ;; "-c"|"--cleanup") CLEANUP=y shift ;; "-b"|"--batch") BATCH=y shift ;; "-p"|"--package") if [ "$2" = "" ] then SKIP_SUBPACKS=y else BUILD_SUBPACK=$2 fi shift 2;; "-h"|"--help") protopkg_help exit ;; "-r"|"--remove") REMOVE_SOURCES=y shift ;; "-d"|"--description") CREATE_DESCRIPTION=y shift ;; --) shift break ;; esac done # install the packages the user specifies protopkg ; exit