You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1157 lines
39 KiB

#!/bin/sh
##
## rpmtool -- RPM Auxiliary Tool
## Copyright (c) 2000-2001 Ralf S. Engelschall <rse@engelschall.com>
##
## 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_name="rpmtool"
prog_vers="1.0.2"
prog_date="03-Aug-2001"
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-2001 Ralf S. Engelschall <rse@engelschall.com>"
echo ''
echo "Usage: $prog_name [<options>] [<cmd-name> [<cmd-options>] [<cmd-args>]]"
echo ''
echo 'Available global <options>:'
echo ' -d, --debug enable internal debugging'
echo ' -v, --version display version information'
echo ' -h, --help display usage help page (this one)'
echo ''
echo 'Available <cmd-name> [<cmd-options>] [<cmd-args>]:'
echo ' platform'
echo ' subst [-v] [-t] [-s] <sed-cmd> [...] -- <file> [...]'
echo ' flags [-m] [-c] [-O] <tool>'
echo ' files [-v] [-o <outfile>] [-r <buildroot>] [<filelist>]'
echo ' user [-c] [-d] [-p <passwd>] [-n <realname>] [-d <homedir>]'
echo ' [-s <shell>] [-u <min-uid>] <username>'
echo ' group [-c] [-d] <groupname> <min-gid> [<username> ...]'
echo ' signal [-v] [-t] [-n] [-c] [-d <delay>] [-p <pid>] [-m <pattern>] <sig> [<sig> ...]'
echo ' config [-v] [-s] [-a] [-r] [-b <ext>] [-p <tagprefix>] [-t <tagname>] [-i <tagid>] <file>'
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=""
;;
subst )
str_usage="[-v] [-t] [-s] <sed-cmd> [...] -- <file> [...]"
arg_spec="3+"
opt_spec="v.t.s."
opt_v=no
opt_t=no
opt_s=no
gen_tmpfile=yes
;;
flags )
str_usage="[-m] [-c] [-O] <tool>"
arg_spec="1="
opt_spec="m.c.O."
opt_m=no
opt_c=no
opt_O=no
;;
files )
gen_tmpfile=yes
str_usage="[-v] [-o <outfile>] [-r <buildroot>] [<filelist>]"
arg_spec="0+"
opt_spec="v.o:r:"
opt_v=no
opt_o=''
opt_r=''
;;
user )
str_usage="[-a] [-r] [-p <passwd>] [-n <realname>] [-d <homedir>] [-s <shell>] [-u <min-uid>] <username>"
arg_spec="1="
opt_spec="a.r.p:n:d:s:u:"
opt_a=no
opt_r=no
opt_p=''
opt_n=''
opt_d=''
opt_s=''
opt_u=1000
;;
group )
str_usage="[-a] [-r] [-g <min-gid>] <groupname> [<username> ...]"
arg_spec="1+"
opt_spec="a.r.g:"
opt_a=no
opt_r=no
opt_g=1000
;;
signal )
str_usage="[-v] [-t] [-n] [-c] [-d <delay>] [-p <pid>] [-m <pattern>] <sig> [<sig> ...]"
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 <ext>] [-p <tagprefix>] [-t <tagname>] [-i <tagid>] <file>"
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
;;
-* )
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'`
# interate 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"
elif [ ".$TEMPDIR" != . ]; then
tmpdir="$TEMPDIR"
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'
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}"
;;
subst )
# substitute variables (in-place)
ops=""
files=""
isop=1
for arg
do
if [ ".$arg" = ".--" ]; then
isop=0
continue
fi
if [ ".$isop" = .1 ]; then
ops="$ops%$arg"
else
files="$files%$arg"
fi
done
cmd='sed'
OIFS="$IFS"; IFS="%"
for op in $ops; do
test ".$op" = . && continue
cmd="$cmd -e '$op'"
done
IFS="$OIFS"
for file in `IFS="%"; echo $files`; do
test ".$file" = . && continue
if [ ! -f $file ]; then
echo "$msgprefix:Warning: file \`$file' not found" 1>&2
continue
fi
if [ ".$opt_v" = .yes ]; then
echo "patching file \`$file'" 1>&2
fi
if [ ".$opt_t" = .yes ]; then
echo "\$ cp -p $file $file.orig"
echo "\$ $cmd <$file.orig >$file"
fi
cp -p $file $file.orig
eval "$cmd <$file.orig >$file"
if [ ".$opt_s" = .yes ]; then
if [ ".$opt_t" = .yes ]; then
echo "\$ touch -r $file.orig $file"
fi
touch -r $file.orig $file
fi
done
;;
flags )
tool="$1"
if [ ".$opt_m" = .yes ]; then
isgmake=no
if [ ".`$tool -v 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.*:* )
n=`/sbin/sysctl hw.ncpu | awk '{ print $2; }'`
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.5*:* )
n=`/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
;;
*:Linux:*:* )
n=`cat /proc/cpuinfo | grep processor | 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:*:* )
n=1 # FIXME
;;
esac
fi
echo "$mflags"
elif [ ".$opt_c" = .yes ]; then
isgcc=no
if [ ".`$tool --version 2>/dev/null | egrep '(2.[789]|3.[01])'`" != . ]; then
isgcc=yes
fi
cflags=''
if [ ".$opt_O" = .yes ]; then
if [ ".$isgcc" = .yes ]; then
cflags="-O2 -pipe"
else
cflags="-O"
fi
fi
echo "$cflags"
fi
;;
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 | sed -e 's/:/ /g'` .; do
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 (<STDIN>) {
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
;;
user )
# calling convention
if [ ".$opt_a" = .no -a ".$opt_r" = .no ]; then
echo "$msgprefix:Error: either -a or -r has to be given" 1>&2
exit 1
fi
if [ ".$opt_a" = .yes -a ".$opt_r" = .yes ]; then
echo "$msgprefix:Error: only -a or -r can be given" 1>&2
exit 1
fi
user=$1
# default values
if [ ".$opt_n" = . ]; then
opt_n="$user"
fi
if [ ".$opt_s" = . ]; then
opt_s=`which false 2>/dev/null`
if [ ".$opt_s" = . ]; then
opt_s="/bin/false"
fi
fi
if [ ".$opt_d" = . ]; then
opt_d="/nowhere"
fi
# add user
if [ ".$opt_a" = .yes ]; then
exists=`grep "^$user:" /etc/passwd`
if [ ".$exists" != . ]; then
echo "$msgprefix:Error: user $user already exists" 1>&2
exit 1
fi
# seek for next free uid
uid=$opt_u
ok=0
while [ ".$ok" = .0 ]; do
u_exists=`grep "^[^:]*:[^:]*:$uid:" /etc/passwd`
g_exists=`grep "^[^:]*:[^:]*:$uid:" /etc/group`
if [ ".$u_exists" = . -a ".$g_exists" = . ]; then
ok=1
break
fi
uid=`expr $uid + 1`
done
# add entry to passwd database
case "$platform" in
*:FreeBSD:[456].*:* | *:NetBSD:1.*:* )
echo "${user}:*:${uid}:${uid}::0:0:${opt_n}:${opt_d}:${opt_s}" >>/etc/master.passwd
(PATH="$PATH:/usr/sbin"; pwd_mkdb -p /etc/master.passwd)
;;
*:Linux:2.*:* )
echo "${user}:*:${uid}:${uid}::${opt_n}:${opt_d}:${opt_s}" >>/etc/passwd
(PATH="$PATH:/usr/sbin"; pwconv)
;;
*:SunOS:5.*:* )
echo "${user}:*:${uid}:${uid}:${opt_n}:${opt_d}:${opt_s}" >>/etc/passwd
(PATH="$PATH:/usr/sbin"; pwconv)
;;
*:OSF1:5.*:* )
echo "${user}:*:${uid}:${uid}:${opt_n}:${opt_d}:${opt_s}" >>/etc/passwd
(PATH="$PATH:/usr/sbin"; mkpasswd /etc/passwd)
;;
*:HP-UX:*:* )
echo "${user}:*:${uid}:${uid}:${opt_n}:${opt_d}:${opt_s}" >>/etc/passwd
;;
esac
# add corresponding entry to group database
echo "${user}:*:${uid}:${user}" >>/etc/group
# remove user
elif [ ".$opt_r" = .yes ]; then
exists=`grep "^$user:" /etc/passwd`
if [ ".$exists" = . ]; then
echo "$msgprefix:Error: user $user does not exist" 1>&2
exit 1
fi
# remove entry from passwd database
case "$platform" in
*:FreeBSD:[456].*:* | *:NetBSD:1.*:* )
cp /etc/master.passwd /etc/master.passwd.old
grep -v "^${user}:" /etc/master.passwd.old >/etc/master.passwd
(PATH="$PATH:/usr/sbin"; pwd_mkdb -p /etc/master.passwd)
rm -f /etc/master.passwd.old
;;
*:Linux:2.*:* | *:SunOS:5.*:* )
cp /etc/passwd /etc/passwd.old
grep -v "^${user}:" /etc/passwd.old >/etc/passwd
(PATH="$PATH:/usr/sbin"; pwconv)
rm -f /etc/passwd.old
;;
*:OSF1:5.*:* )
cp /etc/passwd /etc/passwd.old
grep -v "^${user}:" /etc/passwd.old >/etc/passwd
(PATH="$PATH:/usr/sbin"; mkpasswd /etc/passwd)
rm -f /etc/passwd.old
;;
*:HP-UX:*:* )
cp /etc/passwd /etc/passwd.old
grep -v "^${user}:" /etc/passwd.old >/etc/passwd
rm -f /etc/passwd.old
;;
esac
# remove corresponding entry from group database
cp /etc/group /etc/group.old
grep -v "^${user}:" /etc/group.old >/etc/group
rm -f /etc/group.old
fi
;;
group )
if [ ".$opt_a" = .no -a ".$opt_r" = .no ]; then
echo "$msgprefix:Error: either -a or -r has to be given" 1>&2
exit 1
fi
if [ ".$opt_a" = .yes -a ".$opt_r" = .yes ]; then
echo "$msgprefix:Error: only -a or -r can be given" 1>&2
exit 1
fi
group=$1
# add group
if [ ".$opt_a" = .yes ]; then
exists=`grep "^$group:" /etc/group`
if [ ".$exists" != . ]; then
echo "$msgprefix:Error: group $group already exists" 1>&2
exit 1
fi
# seek for next free gid
gid=$opt_g
ok=0
while [ ".$ok" = .0 ]; do
exists=`grep "^[^:]*:[^:]*:$gid:" /etc/group`
if [ ".$exists" = . ]; then
ok=1
break
fi
gid=`expr $gid + 1`
done
# add entry to group database
echo "${group}:*:${gid}:$*" >>/etc/group
# remove group
elif [ ".$opt_r" = .yes ]; then
exists=`grep "^$group:" /etc/group`
if [ ".$exists" = . ]; then
echo "$msgprefix:Error: group $group does not exist" 1>&2
exit 1
fi
# remove entry from group database
cp /etc/group /etc/group.old
grep -v "^${group}:" /etc/group.old >/etc/group
rm -f /etc/group.old
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
;;
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}</${opt_t}>"
# 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
;;
esac
# cleanup
if [ ".$gen_tmpfile" = .yes ]; then
rm -f $tmpfile >/dev/null 2>&1
fi
# die gracefully ;)
exit 0