diff -r 333964c621f1 -r cb59d6afeb61 openpkg/rpmtool --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/openpkg/rpmtool Tue Jan 06 23:40:39 2009 +0100 @@ -0,0 +1,1155 @@ +#!@l_prefix@/lib/openpkg/bash +## +## rpmtool -- OpenPKG RPM Auxiliary Tool +## Copyright (c) 2000-2007 OpenPKG Foundation e.V. +## Copyright (c) 2000-2007 Ralf S. Engelschall +## +## Permission to use, copy, modify, and distribute this software for +## any purpose with or without fee is hereby granted, provided that +## the above copyright notice and this permission notice appear in all +## copies. +## +## THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 AUTHORS AND COPYRIGHT HOLDERS AND THEIR +## CONTRIBUTORS 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. +## + +prog_path="$0" +prog_name="rpmtool" +prog_vers="1.1.0" +prog_date="05-Mar-2007" + +if [ $# -eq 0 ]; then + echo "$0:Error: invalid command line" 1>&2 + echo "$0:Hint: run \`$0 -h' for usage" 1>&2 + exit 1 +fi +if [ ".$1" = ".-h" -o ".$1" = ".--help" ]; then + echo "This is $prog_name, version $prog_vers ($prog_date)" + echo "Copyright (c) 2000-2004 Ralf S. Engelschall " + echo '' + echo "Usage: $prog_name [] [ [] []]" + echo '' + echo 'Available global :' + echo ' -d, --debug enable internal debugging' + echo ' -v, --version display version information' + echo ' -h, --help display usage help page (this one)' + echo '' + echo 'Available [] []:' + echo ' platform' + echo ' mflags [-O] ' + echo ' cflags [-O] ' + echo ' cppflags [-p ] [ ...]' + echo ' ldflags [-p ] [ ...]' + echo ' files [-v] [-o ] [-r ] []' + echo ' signal [-v] [-t] [-n] [-c] [-d ] [-p ] [-m ] [ ...]' + echo ' config [-v] [-s] [-a] [-r] [-b ] [-p ] [-t ] [-i ] ' + echo ' msg [-b] [-r] [-t ]' + echo '' + exit 0 +fi +if [ ".$1" = ".-v" -o ".$1" = ."--version" ]; then + echo "$prog_name $prog_vers ($prog_date)" + exit 0 +fi +if [ ".$1" = ".-d" -o ".$1" = ."--debug" ]; then + shift + set -x +fi + +tool="$1" +shift +arg_spec="" +opt_spec="" +gen_tmpfile=no + +# configure tool specific option parsing +case $tool in + platform ) + str_usage="" + arg_spec="0=" + opt_spec="" + ;; + mflags ) + str_usage="[-O] " + arg_spec="1=" + opt_spec="O." + opt_O=no + ;; + cflags ) + str_usage="[-O] " + arg_spec="1=" + opt_spec="O." + opt_O=no + ;; + cppflags ) + str_usage="[-p ] [-i] [ ...]" + arg_spec="0+" + opt_spec="p:i." + opt_p="/" + ;; + ldflags ) + str_usage="[-p ] [ ...]" + arg_spec="0+" + opt_spec="p:" + opt_p="/" + ;; + files ) + gen_tmpfile=yes + str_usage="[-v] [-o ] [-r ] []" + arg_spec="0+" + opt_spec="v.o:r:" + opt_v=no + opt_o='' + opt_r='' + ;; + signal ) + str_usage="[-v] [-t] [-n] [-c] [-d ] [-p ] [-m ] [ ...]" + arg_spec="1+" + opt_spec="v.t.n.c.d:p:m:" + opt_v=no + opt_t=no + opt_n=no + opt_c=no + opt_d=1 + opt_p="" + opt_m="" + ;; + config ) + str_usage="[-v] [-s] [-a] [-r] [-b ] [-p ] [-t ] [-i ] " + arg_spec="1=" + opt_spec="v.s.a.r.b:p:t:i:c:" + opt_v=no + opt_s=no + opt_a=no + opt_r=no + opt_b="" + opt_p="#" + opt_t="OpenPKG" + opt_i="" + gen_tmpfile=yes + ;; + msg ) + str_usage="[-b] [-r] [-t ]" + arg_spec="0=" + opt_spec="b.r.t:" + opt_b=no + opt_r=no + opt_t=info + ;; + check-class ) + str_usage="" + arg_spec="1=" + opt_spec="" + ;; + -* ) + echo "$prog_name:Error: unknown option \`$tool'" 2>&1 + echo "$prog_name:Hint: run \`$0 -h' for usage" 2>&1 + exit 1 + ;; + * ) + echo "$prog_name:Error: unknown command \`$tool'" 2>&1 + echo "$prog_name:Hint: run \`$0 -h' for usage" 2>&1 + exit 1 + ;; +esac + +# tool information +toolcmd="$0 $tool" +toolcmdhelp="$prog_name $tool" +msgprefix="$prog_name:$tool" + +# parse argument specification string +eval `echo $arg_spec |\ + sed -e 's/^\([0-9]*\)\([+=]\)/arg_NUMS=\1; arg_MODE=\2/'` + +# parse option specification string +eval `echo h.$opt_spec |\ + sed -e 's/\([a-zA-Z0-9]\)\([.:+]\)/opt_MODE_\1=\2;/g'` + +# iterate over argument line +opt_PREV='' +while [ $# -gt 0 ]; do + # special option stops processing + if [ ".$1" = ".--" ]; then + shift + break + fi + + # determine option and argument + opt_ARG_OK=no + if [ ".$opt_PREV" != . ]; then + # merge previous seen option with argument + opt_OPT="$opt_PREV" + opt_ARG="$1" + opt_ARG_OK=yes + opt_PREV='' + else + # split argument into option and argument + case "$1" in + -[a-zA-Z0-9]*) + eval `echo "x$1" |\ + sed -e 's/^x-\([a-zA-Z0-9]\)/opt_OPT="\1";/' \ + -e 's/";\(.*\)$/"; opt_ARG="\1"/'` + ;; + -[a-zA-Z0-9]) + opt_OPT=`echo "x$1" | cut -c3-` + opt_ARG='' + ;; + *) + break + ;; + esac + fi + + # eat up option + shift + + # determine whether option needs an argument + eval "opt_MODE=\$opt_MODE_${opt_OPT}" + if [ ".$opt_ARG" = . -a ".$opt_ARG_OK" != .yes ]; then + if [ ".$opt_MODE" = ".:" -o ".$opt_MODE" = ".+" ]; then + opt_PREV="$opt_OPT" + continue + fi + fi + + # process option + case $opt_MODE in + '.' ) + # boolean option + eval "opt_${opt_OPT}=yes" + ;; + ':' ) + # option with argument (multiple occurances override) + eval "opt_${opt_OPT}=\"\$opt_ARG\"" + ;; + '+' ) + # option with argument (multiple occurances append) + eval "opt_${opt_OPT}=\"\$opt_${opt_OPT} \$opt_ARG\"" + ;; + * ) + echo "$msgprefix:Error: unknown option: \`-$opt_OPT'" 1>&2 + echo "$msgprefix:Hint: run \`$toolcmdhelp -h' or \`man $prog_name' for details" 1>&2 + exit 1 + ;; + esac +done +if [ ".$opt_PREV" != . ]; then + echo "$msgprefix:Error: missing argument to option \`-$opt_PREV'" 1>&2 + echo "$msgprefix:Hint: run \`$toolcmdhelp -h' or \`man $prog_name' for details" 1>&2 + exit 1 +fi + +# process help option +if [ ".$opt_h" = .yes ]; then + echo "Usage: $toolcmdhelp $str_usage" + exit 0 +fi + +# complain about incorrect number of arguments +case $arg_MODE in + '=' ) + if [ $# -ne $arg_NUMS ]; then + echo "$msgprefix:Error: invalid number of arguments (exactly $arg_NUMS expected)" 1>&2 + echo "$msgprefix:Hint: run \`$toolcmd -h' or \`man $prog_name' for details" 1>&2 + exit 1 + fi + ;; + '+' ) + if [ $# -lt $arg_NUMS ]; then + echo "$msgprefix:Error: invalid number of arguments (at least $arg_NUMS expected)" 1>&2 + echo "$msgprefix:Hint: run \`$toolcmd -h' or \`man $prog_name' for details" 1>&2 + exit 1 + fi + ;; +esac + +# establish a temporary file on request +if [ ".$gen_tmpfile" = .yes ]; then + if [ ".$TMPDIR" != . ]; then + tmpdir="$TMPDIR" + else + tmpdir="/tmp" + fi + tmpfile="$tmpdir/.$prog_name.$$" + rm -f $tmpfile >/dev/null 2>&1 + touch $tmpfile +fi + +# provide a few useful variables +NL=" +" +TAB=" " +DIFS=" ${TAB}${NL}" + +# determine platform information +platform_machine=`(uname -m) 2>/dev/null` ||\ +platform_machine=`(uname -p) 2>/dev/null` ||\ +platform_machine='unknown' +if [ ".$platform_machine" = ".Power Macintosh" ]; then + platform_machine=`(uname -p) 2>/dev/null` +fi +platform_release=`(uname -r) 2>/dev/null` ||\ +platform_release='unknown' +platform_system=`(uname -s) 2>/dev/null` ||\ +platform_system='unknown' +platform_version=`(uname -v) 2>/dev/null` ||\ +platform_version='unknown' +platform="${platform_machine}:${platform_system}:${platform_release}:${platform_version}" + +# dispatch into tools +case $tool in + platform ) + # provide unique platform id + m=`echo "$platform_machine" | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + s=`echo "$platform_system" | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + r=`echo "$platform_release" | sed -e 's;-.*$;;'` + echo "${m}-${s}${r}" + ;; + + mflags ) + tool="$1" + isgmake=no + if [ ".`$tool -v -f /dev/null 2>/dev/null | grep 'GNU Make'`" != . ]; then + isgmake=yes + fi + mflags='' + if [ ".$isgmake" = .yes ]; then + mflags="--no-print-directory" + fi + if [ ".$opt_O" = .yes ]; then + case $platform in + *:SunOS:5.*:* | *:OSF1:*:* ) + if [ ".$isgmake" = .yes ]; then + n=`(/bin/uname -X) 2>/dev/null | grep -i NumCPU | awk '{ print $3; }'` + if [ ".$n" != . ]; then + if [ $n -gt 1 ]; then + n=`expr $n \* 2` + mflags="$mflags -j$n" + fi + fi + fi + ;; + *:FreeBSD:[4-8].*:* ) + n=`/sbin/sysctl -n hw.ncpu` + if [ ".$n" != . ]; then + if [ $n -gt 1 ]; then + n=`expr $n \* 2` + mflags="$mflags -j$n" + if [ ".$isgmake" = .no ]; then + mflags="$mflags -B" + fi + fi + fi + ;; + *:NetBSD:1.[56]*:* | *:NetBSD:[2345].*:* ) + n=`/sbin/sysctl -n hw.ncpu` + if [ ".$n" != . ]; then + if [ $n -gt 1 ]; then + n=`expr $n \* 2` + mflags="$mflags -j$n" + if [ ".$isgmake" = .no ]; then + mflags="$mflags -B" + fi + fi + fi + ;; + *:Linux:*:* ) + n=`grep ^processor /proc/cpuinfo | wc -l | awk '{ print $1; }'` + if [ ".$n" != . ]; then + if [ $n -gt 1 ]; then + n=`expr $n \* 2` + mflags="$mflags -j$n" + fi + fi + ;; + *:HP-UX:*:* ) + if [ ".$isgmake" = .yes ]; then + n=`ioscan -d processor -k -F | wc -l` + if [ ".$n" != . ]; then + if [ $n -gt 1 ]; then + n=`expr $n \* 2` + mflags="$mflags -j$n" + fi + fi + fi + ;; + *:IRIX64:6.*:* ) + if [ ".$isgmake" = .yes ]; then + n=`/usr/sbin/sysconf | awk '/NUM_PROCESSORS/ { print $2; }'` + if [ ".$n" != . ]; then + if [ $n -gt 1 ]; then + n=`expr $n \* 2` + mflags="$mflags -j$n" + fi + fi + fi + ;; + *:Darwin:*:* ) + n=`/usr/sbin/sysctl hw.ncpu | awk '{ print $3; }'` + if [ ".$n" != . ]; then + if [ $n -gt 1 ]; then + n=`expr $n \* 2` + mflags="$mflags -j$n" + if [ ".$isgmake" = .no ]; then + mflags="$mflags -B" + fi + fi + fi + ;; + *:AIX:*:* ) + if [ ".$isgmake" = .yes ]; then + if [ -x /usr/sbin/lsdev ]; then + n=`/usr/sbin/lsdev -C -c processor -S available | wc -l | awk '{ print $1; }'` + if [ ".$n" != . ]; then + if [ $n -gt 1 ]; then + n=`expr $n \* 2` + mflags="$mflags -j$n" + fi + fi + fi + fi + ;; + esac + fi + echo "x$mflags" | sed -e 's;^x;;' + ;; + + cflags ) + tool="$1" + echo $tool | grep ^/ >/dev/null + if [ $? -eq 0 ]; then + if [ ! -x "$tool" -o -d "$tool" ]; then + echo "$msgprefix:Error: specified tool \`$tool' not found or not executable" 1>&2 + exit 1 + fi + else + shtool=`echo $prog_path | sed -e 's;/[^/]*$;/shtool;'` + sh $shtool path --suppress $tool + if [ $? -ne 0 ]; then + echo "$msgprefix:Error: specified tool \`$tool' not found in PATH" 1>&2 + exit 1 + fi + fi + isgcc=no + if [ ".`($tool -v; $tool --version) &1 | grep -i 'gcc'`" != . ]; then + isgcc=yes + fi + cflags='' + if [ ".$opt_O" = .yes ]; then + if [ ".$isgcc" = .yes ]; then + case "$platform:`$tool -dumpversion 2>/dev/null`" in + *:NetBSD:1.6*:*:2.* ) + # NetBSD 1.6.x with GCC 2.95.x suffers from memory + # exhaustion problems under GCC optimizations. + ;; + * ) + cflags="-O2" + ;; + esac + if [ ".`$tool -v 2>/dev/null | grep 'with-gnu-as'`" != . ] || \ + [ ".`(as --version /dev/null | grep 'GNU'`" != . ]; then + cflags="$cflags -pipe" + fi + else + cflags="-O" + fi + fi + case "$platform" in + amd64:FreeBSD:*:* | ia64:FreeBSD:*:* | sparc64:FreeBSD:*:* | x86_64:Linux:*:* ) + # at least under FreeBSD on amd64, ia64 and sparc64 + # the GNU binutils strictly require Position In- + # dependent Code (PIC) when Dynamic Shared Objects + # (DSO) are involved. As an ugly workaround we + # build everything with PIC there, although this is + # more than required. We also can assume that the C + # compiler is always GCC, either the OpenPKG one or + # the FreeBSD one. + cflags="-fPIC" + ;; + esac + echo "x$cflags" | sed -e 's;^x;;' + ;; + + cppflags ) + std=0 + cppflags="" + for pkg in .. $*; do + [ ".$pkg" = ... ] && continue + if [ ".$pkg" = .. ]; then + cppflags="$cppflags -I${opt_p}/include" + std=1 + else + cppflags="$cppflags -I${opt_p}/include/$pkg" + fi + done + if [ $std -eq 0 ]; then + cppflags="-I${opt_p}/include$cppflags" + fi + if [ ".$opt_i" = .yes ]; then + arch="unknown"; os_name="unknown"; os_vers="0" + shtool=`echo $prog_path | sed -e 's;/[^/]*$;/shtool;'` + eval `sh $shtool platform -U -S ":" -C "" -F "%:%" |\ + sed -e 's/^\(.*\):\(.*\):\(.*\)$/arch="\1"; os_name="\2"; os_vers="\3";/'` + V=0; R=0; L=0 + eval `echo "$os_vers" |\ + sed -e 's/^/X/' \ + -e 's/^X[^0-9]*\([0-9][0-9]*\)[^0-9][^0-9]*\([0-9][0-9]*\)[^0-9][^0-9]*\([0-9][0-9]*\).*$/V="\1"; R="\2"; L="\3";/' \ + -e 's/^X[^0-9]*\([0-9][0-9]*\)[^0-9][^0-9]*\([0-9][0-9]*\).*$/V="\1"; R="\2";/' \ + -e 's/^X[^0-9]*\([0-9][0-9]*\).*$/V="\1";/' \ + -e 's/^X.*$/:/'` + os_vers=`echo . | awk '{ printf("%02d%02d%02d", V, R, L); }' V="$V" R="$R" L="$L"` + cppflags="$cppflags -D__OPENPKG_${arch} -D__OPENPKG_${os_name}=${os_vers}" + fi + echo "x$cppflags" | sed -e 's;^x;;' -e 's;^ *;;' + ;; + + ldflags ) + std=0 + ldflags="" + for pkg in .. $*; do + [ ".$pkg" = ... ] && continue + if [ ".$pkg" = .. ]; then + ldflags="$ldflags -L${opt_p}/lib" + std=1 + else + ldflags="$ldflags -L${opt_p}/lib/$pkg" + fi + done + if [ $std -eq 0 ]; then + ldflags="-L${opt_p}/lib$ldflags" + fi + echo "x$ldflags" | sed -e 's;^x;;' -e 's;^ *;;' + ;; + + files ) + # if a Perl interpreter is available, we perform the operation + # with it because Perl is a magnitude (factor 10!) faster than + # what we can do here in Bourne-Shell. + perl='' + for dir in `echo "$PATH:@l_prefix@/lib/openpkg" | sed -e 's/:/ /g'` .; do + [ ".$dir" = .. -o ".$dir" = . ] && continue + for tool in perl5 perl miniperl; do + if [ -f "$dir/$tool" ]; then + perl="$dir/$tool" + break + fi + done + if [ ".$perl" != . ]; then + break + fi + done + if [ ".$perl" != . ]; then + cat >$tmpfile <<'EOT' + ## + ## PERL IMPLEMENTATION (FAST) + ## + + my $opt_v = 0; + my $opt_o = ''; + my $opt_r = ''; + while ($ARGV[0] =~ m|^-(.)(.*)$|) { + my ($opt, $arg) = ($1, $2); + shift(@ARGV); + unshift(@ARGV, $arg) if ($arg ne ''); + $opt_v = 1 if ($opt eq 'v'); + $opt_o = shift(@ARGV) if ($opt eq 'o'); + $opt_r = shift(@ARGV) if ($opt eq 'r'); + } + + # remember the build root in a reasonable short variable ;) + my $br = "$opt_r"; + + # read input file list + my @L = (); + if ($#ARGV == -1 or ($#ARGV == 0 and $ARGV[0] eq "-")) { + # read file list from stdin + while () { + s/\n$//s; + push(@L, $_); + } + } + else { + # read file list from argument line + @L = @ARGV; + } + + # PASS 1: PREPARATION AND SYNTACTICAL EXPANSION + if ($opt_v == 1) { + print STDERR "rpmtool:files: pass 1 (preparation and syntactical expansions)\n"; + } + my @T = (); + my $l; + foreach $l (@L) { + # replace tabs with spaces, reduce multiple spaces to single + # spaces, and remove leading and trailing spaces + $l =~ s|[ \t\n]+| |sg; + $l =~ s|^[ \t]+||sg; + $l =~ s|[ \t]+$||sg; + + # move tags to end of entry for easier parsing + 1 while ($l =~ s|^(%\S+) (.+)|$2 $1|); + + # use `:' as a dummy path for tag-only entries (like `%defattr') + # to avoid special cases in the later processing + if ($l =~ m|^%.+|) { + $l = ": $l"; + } + + # split entry into path and optional tags + my ($p, $t) = ($l =~ m|^(\S+)(.*)$|); + + # expand `{foo,bar,quux}' constructs in path (silent + # assumtion to make life easier is that the constructs + # occurs only once in a path!) + if ($p =~ m|^(.*)\{([^\}]+)\}(.*)$|) { + # split path into prolog, the set construct, and the epilog + my ($pro, $set, $epi) = ($1, $2, $3); + + # repeat prolog and epilog for all elements in set + my $x; + foreach $x (split(/,/, $set)) { + push(@T, "${pro}${x}${epi}${t}"); + } + } + else { + # else just take over the entry as is + push(@T, $l); + } + } + @L = @T; + + # PASS 2: FILESYSTEM-BASED EXPANSIONS + if ($opt_v == 1) { + print STDERR "rpmtool:files: pass 2 (filesystem-based expansions)\n"; + } + @T = (); + foreach $l (@L) { + # split entry into path and optional tags + my ($p, $t) = ($l =~ m|^(\S*)(.*)$|); + + # expand... + if (-d "$br$p" and $t !~ m|.*%dir.*|) { + # expand path because it is not tagged with %dir + my @X = `cd "$br$p" && find . -print`; + my $x; + foreach $x (@X) { + $x =~ s|\n$||s; + $x =~ s|^\.|$p|s; + push(@T, "${x}${t}"); + } + } + else { + # expand path wildcards (`*' and `[..]') + # (if not wildcards are present, this doesn't harm) + my @X = glob("$br$p"); + my $x; + foreach $x (@X) { + my $brqm = quotemeta($br); + $x =~ s|^$brqm||s; + push(@T, "${x}${t}"); + } + } + } + @L = @T; + + # PASS 3: DUPLICATION REMOVAL AND CLEANUP + if ($opt_v == 1) { + print STDERR "rpmtool:files: pass 3 (duplication removal and cleanup)\n"; + } + @T = (); + foreach $l (@L) { + # split entry into path and optional tags + my ($p, $t) = ($l =~ m|^(\S*)(.*)$|); + + # add %dir tag if entry is a directory, but still not + # tagged as such (else RPM would again expand it recursively) + if (-d "$br$p") { + if ($t !~ m|%dir|) { + $t .= " %dir"; + } + } + + # remove duplicate entries in already processed part + # (but make sure we keep the entries with the dummy tags) + if ($p ne ":") { + my @T2 = (); + foreach $t (@T) { + my $pqm = quotemeta($p); + next if ($t =~ m|^$pqm | or $t eq $p); + push(@T2, $t); + } + @T = @T2; + } + + # keep entry only if no %not tag is present + # (else all entries are removed) + if ($t !~ m|.*%not.*|) { + push(@T, "${p}${t}"); + } + } + @L = @T; + + # write out new file list + @T = (); + foreach $l (@L) { + $l =~ s|^(\S+) (.*)$|$2 $1|sg; + $l =~ s|^\s+||s; + $l =~ s|\s+$||s; + $l =~ s|\s+:$||s; + push(@T, $l); + } + @L = @T; + if ($opt_o eq '' or $opt_o eq '-') { + print STDOUT join("\n", @L)."\n"; + } + else { + open(FP, ">$opt_o"); + print FP join("\n", @L)."\n"; + close(FP); + } +EOT + cmd="$perl $tmpfile"; + if [ ".$opt_v" = .yes ]; then + cmd="$cmd -v" + fi + if [ ".$opt_o" != . ]; then + cmd="$cmd -o \"$opt_o\"" + fi + if [ ".$opt_r" != . ]; then + cmd="$cmd -r \"$opt_r\"" + fi + for arg + do + cmd="$cmd \"$arg\"" + done + eval "$cmd" + else + ## + ## BOURNE-SHELL IMPLEMENTATION (PORTABLE) + ## + + # remember the build root in a reasonable short variable ;) + br="$opt_r" + + # make sure filename expansion is disabled per default + set -f + + # read input file list + L='' + if [ $# -eq 0 ] || [ $# -eq 1 -a ".$1" = ".-" ]; then + # read file list from stdin + L=`cat` + else + # read file list from argument line + for arg + do + L="$L$NL$arg" + done + fi + + # PASS 1: PREPARATION AND SYNTACTICAL EXPANSION + if [ ".$opt_v" = .yes ]; then + echo "rpmtool:files: pass 1 (preparation and syntactical expansions)" 1>&2 + fi + T='' + OIFS="$IFS"; IFS="$NL" + for l in $L; do + [ ".$l" = . ] && continue + + # replace tabs with spaces, reduce multiple spaces to single + # spaces, and remove leading and trailing spaces + l=`echo "$l" | sed -e "s;${TAB}; ;g" -e 's; *; ;g' -e 's;^ *;;' -e 's; *$;;'` + + # move tags to end of entry for easier parsing + while [ ".`echo \"$l\" | grep '^%[^ ]* .*'`" != . ]; do + l=`echo "$l" | sed -e 's;^\(%[^ ]*\) \(.*\);\2 \1;'` + done + + # use `:' as a dummy path for tag-only entries (like `%defattr') + # to avoid special cases in the later processing + if [ ".`echo \"$l\" | grep '^%.*'`" != . ]; then + l=": $l" + fi + + # split entry into path and optional tags + eval `echo ".$l" | sed -e 's;^\.\([^ ]*\)\(.*\)$;p="\1" t="\2";'` + + # expand `{foo,bar,quux}' constructs in path (silent + # assumtion to make life easier is that the constructs + # occurs only once in a path!) + if [ ".`echo \".$p\" | grep '^\..*{[^}]*}.*$'`" != . ]; then + + # split path into prolog, the set construct, and the epilog + eval `echo ".$p" | sed -e 's;^\.\(.*\){\([^}]*\)}\(.*\)$;pro="\1" set="\2" epi="\3";'` + + # repeat prolog and epilog for all elements in set + OIFS2="$IFS"; IFS="," + for x in $set; do + T="$T$NL${pro}${x}${epi}${t}" + done + IFS="$OIFS2" + else + # else just take over the entry as is + T="$T$NL$l" + fi + done + L="$T" + IFS="$OIFS" + + # PASS 2: FILESYSTEM-BASED EXPANSIONS + if [ ".$opt_v" = .yes ]; then + echo "rpmtool:files: pass 2 (filesystem-based expansions)" 1>&2 + fi + T='' + OIFS="$IFS"; IFS="$NL" + for l in $L; do + [ ".$l" = . ] && continue + + # split entry into path and optional tags + eval `echo ".$l" | sed -e 's;^\.\([^ ]*\)\(.*\)$;p="\1" t="\2";'` + + # expand... + if [ -d "$br$p" -a ".`expr \".$t\" : '\..*%dir.*'`" = .0 ]; then + # expand path because it is not tagged with %dir + OIFS2="$IFS"; IFS="$DIFS" + for x in `cd "$br$p" && find . -print | sed -e "s;^\\.;$p;"`; do + T="$T$NL${x}${t}" + done + IFS="$OIFS2" + else + # expand path wildcards (`*' and `[..]') + # (if not wildcards are present, this doesn't harm) + OIFS2="$IFS"; IFS="$DIFS" + for x in `(set +f; echo $br$p) | sed -e "s;^$br;;" -e "s; $br; ;g"`; do + T="$T$NL${x}${t}" + done + IFS="$OIFS2" + fi + done + IFS="$OIFS" + L="$T" + + # PASS 3: DUPLICATION REMOVAL AND CLEANUP + if [ ".$opt_v" = .yes ]; then + echo "rpmtool:files: pass 3 (duplication removal and cleanup)" 1>&2 + fi + T='' + OIFS="$IFS"; IFS="$NL" + for l in $L; do + [ ".$l" = . ] && continue + + # split entry into path and optional tags + eval `echo ".$l" | sed -e 's;^\.\([^ ]*\)\(.*\)$;p="\1" t="\2";'` + + # add %dir tag if entry is a directory, but still not + # tagged as such (else RPM would again expand it recursively) + if [ -d "$br$p" ]; then + if [ ".`expr \".$t\" : '\..*%dir.*'`" = .0 ]; then + t="$t %dir" + fi + fi + + # remove duplicate entries in already processed part + # (but make sure we keep the entries with the dummy tags) + if [ ".$p" != ".:" ]; then + T=`echo "$T" | grep -v "^$p " | grep -v "^$p\$"` + fi + + # keep entry only if no %not tag is present + # (else all entries are removed) + if [ ".`expr \".$t\" : '\..*%not.*'`" = .0 ]; then + T="$T$NL${p}${t}" + fi + done + IFS="$OIFS" + L="$T" + + # write out new file list + if [ ".$opt_o" = . -o ".$opt_o" = ".-" ]; then + outcmd="cat" + else + outcmd="cat > $opt_o" + fi + echo "$L" |\ + sed -e '/^$/d' \ + -e 's;^\([^ ]*\) *\(.*\)$;\2 \1;g' \ + -e 's;^ *;;' \ + -e 's; *$;;' \ + -e 's; *:$;;' | eval $outcmd + fi + ;; + + signal ) + if [ ".$opt_p" = . -a ".$opt_m" = . ]; then + echo "$msgprefix:Error: either option -p or -m has to be specified" 1>&2 + exit 1 + fi + case "$platform" in + *:FreeBSD:*:* | *:NetBSD:*:* ) + cmd0="ps -ax -o pid" + cmd1="ps -ax -o command" + cmd2="ps -ax -o pid,command" + cmd3="ps -ax -o pid,ppid" + ;; + *:Linux:*:* | *:OSF1:5.*:* ) + cmd0="ps axo pid" + cmd1="ps axo cmd" + cmd2="ps axo pid,cmd" + cmd3="ps axo pid,ppid" + ;; + *:SunOS:5.*:* ) + cmd0="ps -ef -o pid" + cmd1="ps -ef -o args" + cmd2="ps -ef -o pid,args" + cmd3="ps -ef -o pid,ppid" + ;; + *:HP-UX:*:* ) + cmd0="ps -ef" # FIXME + cmd1="ps -ef" # FIXME + cmd2="ps -ef" # FIXME + cmd3="ps -ef" # FIXME + ;; + *:IRIX64:6.*:* ) + cmd0="ps -ef -o pid" + cmd1="ps -ef -o args" + cmd2="ps -ef -o pid,args" + cmd3="ps -ef -o pid,ppid" + ;; + *:Darwin:*:* ) + cmd0="ps -ax -opid" + cmd1="ps -ax -ocommand" + cmd2="ps -ax -opid,command" + cmd3="ps -ax -opid,ppid" + esac + # try all signals in order + i=$# + for sig in "$@"; do + # check whether program is still running/active + active="" + if [ ".$opt_p" != . ]; then + active=`$cmd0 | grep "$opt_p" | grep -v grep | grep -v rpmtool` + elif [ ".$opt_m" != . ]; then + active=`$cmd1 | grep "$opt_m" | grep -v grep | grep -v rpmtool` + fi + if [ ".$active" = . ]; then + break + fi + + # send signal to program + if [ ".$opt_p" != . ]; then + pids="$opt_p" + elif [ ".$opt_m" != . ]; then + pids=`$cmd2 | sed -e "s;^[ ${TAB}]*;;" | egrep "[0-9]* .*$opt_m" |\ + grep -v grep | grep -v rpmtool |\ + awk '{ printf("%s\n", $1); }'` + fi + for pid in $pids; do + if [ ".$opt_v" = .yes ]; then + echo "sending $sig signal to process $pid" + fi + if [ ".$opt_t" = .yes ]; then + echo "kill -$sig $pid" + fi + if [ ".$opt_n" = .no ]; then + eval "kill -$sig $pid" + fi + done + + # optionally send signal to childs of program + if [ ".$opt_c" = .yes ]; then + for pid in $pids; do + cpids=`$cmd3 | sed -e "s;^[ ${TAB}]*;;" | egrep "[0-9]* $pid" |\ + grep -v grep | grep -v rpmtool |\ + awk '{ printf("%s\n", $1); }'` + for cpid in $cpids; do + if [ ".$opt_v" = .yes ]; then + echo "sending $sig signal to child process $cpid" + fi + if [ ".$opt_t" = .yes ]; then + echo "kill -$sig $cpid" + fi + if [ ".$opt_n" = .no ]; then + eval "kill -$sig $cpid >/dev/null 2>&1" + fi + done + done + fi + + # perform optional delay + i=`expr $i - 1` + if [ $i -gt 0 ]; then + if [ ".$opt_d" != . -a ".$opt_d" != . ]; then + sleep $opt_d + fi + fi + done + ;; + + config ) + # usage consistency + if [ ".$opt_a" = .no -a ".$opt_r" = .no ]; then + echo "$msgprefix:Error: either option -a or -r has to be specified" 1>&2 + exit 1 + fi + configfile="$1" + + # determine block markers + block_start="${opt_p}<${opt_t}" + if [ ".$opt_i" != . ]; then + block_start="${block_start} id=\"${opt_i}\"" + fi + block_start="${block_start}>" + block_end="${opt_p}" + + # slash-escaped versions of block markers (for sed(3) call) + block_start_esc=`echo "$block_start" | sed -e 's;/;\\\\/;g'` + block_end_esc=`echo "$block_end" | sed -e 's;/;\\\\/;g'` + + # determine backup extension + case "X$opt_b" in + X ) ext=".bak" ;; + X.* ) ext="$opt_b" ;; + X* ) ext=".$opt_b" ;; + esac + + # check for block in config file + if [ -f $configfile ]; then + check=`grep "^${block_start}" $configfile` + else + touch $configfile + check="" + fi + + # add entry + if [ ".$opt_a" = .yes ]; then + if [ ".$check" != . ]; then + if [ ".$opt_s" = .yes ]; then + exit 0 + else + echo "$msgprefix:Error: config entry already exists" 1>&2 + exit 1 + fi + fi + cp $configfile $configfile$ext + echo "${block_start}" >$tmpfile + cat >>$tmpfile + echo "${block_end}" >>$tmpfile + cat $tmpfile >>$configfile + + # remove entry + elif [ ".$opt_r" = .yes ]; then + if [ ".$check" = . ]; then + if [ ".$opt_s" = .yes ]; then + exit 0 + else + echo "$msgprefix:Error: config entry does not exist" 1>&2 + exit 1 + fi + fi + cp $configfile $configfile$ext + sed -e "/^${block_start_esc}/,/^${block_end_esc}/d" \ + <$configfile$ext >$configfile + fi + + # verbosity + if [ ".$opt_v" = .yes ]; then + (diff -u1 $configfile$ext $configfile >$tmpfile) 2>/dev/null + if [ ".`cat $tmpfile`" = . ]; then + (diff -C1 $configfile$ext $configfile >$tmpfile) 2>/dev/null + if [ ".`cat $tmpfile`" = . ]; then + if [ ".$opt_s" = .no ]; then + echo "$msgprefix:Warning: unable to show difference for config file \`$configfile'" 1>&2 + fi + fi + fi + echo "editing $configfile:" + cat $tmpfile + fi + + # optionally remove backup file + if [ ".$opt_b" = . ]; then + rm -f $configfile$ext + fi + ;; + + msg ) + # optionally beep before message + if [ ".$opt_b" = .yes ]; then + echo . | awk '{ printf("%c", 7); }' + fi + title="" + case $opt_t in + info ) title="-------" ;; + notice ) title="Notice-" ;; + warn ) title="Warning" ;; + error ) title="Error--" ;; + * ) echo "$msgprefix:Error: invalid message type \`$opt_t'" 1>&2; exit 1 ;; + esac + + # display message + if [ ".$opt_r" != .yes ]; then + echo . | awk '{ printf("\r"); }' + fi + echo "+----------------------------------${title}------------------------------------+" + expand -t 8 | sed -e 's; *$;;' | awk '{ printf("| %-75s |\n", substr($0, 0, 75)); }' + echo "+-----------------------------------------------------------------------------+" + ;; + check-class ) + # check package class from within .spec file macro expansion for %prep section + class="$1"; shift + case "$class" in + CORE|BASE ) + ;; + PLUS ) + echo "set +x" + ( echo "This OpenPKG package is of class PLUS." + echo "This means it is still in extended QUALITY ASSURANCE state." + echo "Hence it is still NOT ready for careless use." + echo "Do not use it in critical production environments." + echo "It might be still potentially unstable under run-time." + ) | sh $prog_path msg -r -t notice | sed -e 's;^;echo ";' -e 's;$;";' + echo "set -x" + ;; + EVAL ) + echo "set +x" + ( echo "This OpenPKG package is of class EVAL." + echo "This means it is still in EVALUATION and QUALITY ASSURANCE state." + echo "Hence it is still NOT ready for general use." + echo "Do not use it in production environments." + echo "It might be unstable under run-time or still incompletely packaged." + ) | sh $prog_path msg -r -t warn | sed -e 's;^;echo ";' -e 's;$;";' + echo "set -x" + ;; + JUNK ) + echo "set +x" + ( echo "This OpenPKG package is of class JUNK." + echo "This means it is still in DEVELOPMENT state." + echo "Hence it is still NOT ready even for general evaluation." + echo "Do not use it at all, except in development environments!" + echo "It is definitely unstable and incompletely packaged." + ) | sh $prog_path msg -r -t warn | sed -e 's;^;echo ";' -e 's;$;";' + echo "set -x" + ;; + esac + ;; +esac + +# cleanup +if [ ".$gen_tmpfile" = .yes ]; then + rm -f $tmpfile >/dev/null 2>&1 +fi + +# die gracefully ;) +exit 0 +