3
## GNU shtool -- The GNU Portable Shell Tool
4
## Copyright (c) 1994-2005 Ralf S. Engelschall <rse@engelschall.com>
6
## See http://www.gnu.org/software/shtool/ for more information.
7
## See ftp://ftp.gnu.org/gnu/shtool/ for latest version.
9
## Version: 2.0.2 (15-Jun-2005)
10
## Contents: 4/19 available modules
14
## This program is free software; you can redistribute it and/or modify
15
## it under the terms of the GNU General Public License as published by
16
## the Free Software Foundation; either version 2 of the License, or
17
## (at your option) any later version.
19
## This program is distributed in the hope that it will be useful,
20
## but WITHOUT ANY WARRANTY; without even the implied warranty of
21
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22
## General Public License for more details.
24
## You should have received a copy of the GNU General Public License
25
## along with this program; if not, write to the Free Software
26
## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
27
## USA, or contact Ralf S. Engelschall <rse@engelschall.com>.
29
## NOTICE: Given that you include this file verbatim into your own
30
## source tree, you are justified in saying that it remains separate
31
## from your package, and that this way you are simply just using GNU
32
## shtool. So, in this situation, there is no requirement that your
33
## package itself is licensed under the GNU General Public License in
34
## order to take advantage of GNU shtool.
38
## Usage: shtool [<options>] [<cmd-name> [<cmd-options>] [<cmd-args>]]
40
## Available commands:
41
## echo Print string with optional construct expansion
42
## install Install a program, script or datafile
43
## mkdir Make one or more directories
44
## path Deal with program paths
46
## Not available commands (because module was not built-in):
47
## mdate Pretty-print modification time of a file or dir
48
## table Pretty-print a field-separated list as a table
49
## prop Display progress with a running propeller
50
## move Move files with simultaneous substitution
51
## mkln Make link with calculation of relative paths
52
## mkshadow Make a shadow tree through symbolic links
53
## fixperm Fix file permissions inside a source tree
54
## rotate Logfile rotation
55
## tarball Roll distribution tarballs
56
## subst Apply sed(1) substitution operations
57
## platform Platform Identification Utility
58
## arx Extended archive command
59
## slo Separate linker options by library class
60
## scpp Sharing C Pre-Processor
61
## version Maintain a version information file
65
echo "$0:Error: invalid command line" 1>&2
66
echo "$0:Hint: run \`$0 -h' for usage" 1>&2
69
if [ ".$1" = ".-h" ] || [ ".$1" = ".--help" ]; then
70
echo "This is GNU shtool, version 2.0.2 (15-Jun-2005)"
71
echo "Copyright (c) 1994-2005 Ralf S. Engelschall <rse@engelschall.com>"
72
echo "Report bugs to <bug-shtool@gnu.org>"
74
echo "Usage: shtool [<options>] [<cmd-name> [<cmd-options>] [<cmd-args>]]"
76
echo 'Available global <options>:'
77
echo ' -v, --version display shtool version information'
78
echo ' -h, --help display shtool usage help page (this one)'
79
echo ' -d, --debug display shell trace information'
80
echo ' -r, --recreate recreate this shtool script via shtoolize'
82
echo 'Available <cmd-name> [<cmd-options>] [<cmd-args>]:'
83
echo ' echo [-n|--newline] [-e|--expand] [<string> ...]'
84
echo ' install [-v|--verbose] [-t|--trace] [-d|--mkdir] [-c|--copy]'
85
echo ' [-C|--compare-copy] [-s|--strip] [-m|--mode <mode>]'
86
echo ' [-o|--owner <owner>] [-g|--group <group>] [-e|--exec'
87
echo ' <sed-cmd>] <file> [<file> ...] <path>'
88
echo ' mkdir [-t|--trace] [-f|--force] [-p|--parents] [-m|--mode'
89
echo ' <mode>] [-o|--owner <owner>] [-g|--group <group>] <dir>'
91
echo ' path [-s|--suppress] [-r|--reverse] [-d|--dirname] [-b|--basename]'
92
echo ' [-m|--magic] [-p|--path <path>] <str> [<str> ...]'
94
echo 'Not available <cmd-name> (because module was not built-in):'
95
echo ' mdate [-n|--newline] [-z|--zero] [-s|--shorten] [-d|--digits]'
96
echo ' [-f|--field-sep <str>] [-o|--order <spec>] <path>'
97
echo ' table [-F|--field-sep <sep>] [-w|--width <width>] [-c|--columns'
98
echo ' <cols>] [-s|--strip <strip>] <str><sep><str>...'
99
echo ' prop [-p|--prefix <str>]'
100
echo ' move [-v|--verbose] [-t|--trace] [-e|--expand] [-p|--preserve]'
101
echo ' <src-file> <dst-file>'
102
echo ' mkln [-t|--trace] [-f|--force] [-s|--symbolic] <src-path>'
103
echo ' [<src-path> ...] <dst-path>'
104
echo ' mkshadow [-v|--verbose] [-t|--trace] [-a|--all] <src-dir> <dst-dir>'
105
echo ' fixperm [-v|--verbose] [-t|--trace] <path> [<path> ...]'
106
echo ' rotate [-v|--verbose] [-t|--trace] [-f|--force] [-n|--num-files'
107
echo ' <count>] [-s|--size <size>] [-c|--copy] [-r|--remove]'
108
echo ' [-a|--archive-dir <dir>] [-z|--compress [<tool>:]<level>]'
109
echo ' [-b|--background] [-d|--delay] [-p|--pad <len>] [-m|--mode'
110
echo ' <mode>] [-o|--owner <owner>] [-g|--group <group>] [-M|--migrate'
111
echo ' <cmd>] [-P|--prolog <cmd>] [-E|--epilog <cmd>] <file> [...]'
112
echo ' tarball [-t|--trace] [-v|--verbose] [-o|--output <tarball>]'
113
echo ' [-c|--compress <prog>] [-d|--directory <dir>] [-u|--user'
114
echo ' <user>] [-g|--group <group>] [-e|--exclude <pattern>]'
115
echo ' <path> [<path> ...]'
116
echo ' subst [-v|--verbose] [-t|--trace] [-n|--nop] [-w|--warning]'
117
echo ' [-q|--quiet] [-s|--stealth] [-i|--interactive] [-b|--backup'
118
echo ' <ext>] [-e|--exec <cmd>] [-f|--file <cmd-file>] [<file>]'
120
echo ' platform [-F|--format <format>] [-S|--sep <string>] [-C|--conc'
121
echo ' <string>] [-L|--lower] [-U|--upper] [-v|--verbose]'
122
echo ' [-c|--concise] [-n|--no-newline] [-t|--type <type>]'
123
echo ' [-V|--version] [-h|--help]'
124
echo ' arx [-t|--trace] [-C|--command <cmd>] <op> <archive> [<file>'
126
echo ' slo [-p|--prefix <str>] -- -L<dir> -l<lib> [-L<dir> -l<lib>'
128
echo ' scpp [-v|--verbose] [-p|--preserve] [-f|--filter <filter>]'
129
echo ' [-o|--output <ofile>] [-t|--template <tfile>] [-M|--mark'
130
echo ' <mark>] [-D|--define <dname>] [-C|--class <cname>]'
131
echo ' <file> [<file> ...]'
132
echo ' version [-l|--language <lang>] [-n|--name <name>] [-p|--prefix'
133
echo ' <prefix>] [-s|--set <version>] [-e|--edit] [-i|--increase'
134
echo ' <knob>] [-d|--display <type>] <file>'
138
if [ ".$1" = ".-v" ] || [ ".$1" = ".--version" ]; then
139
echo "GNU shtool 2.0.2 (15-Jun-2005)"
142
if [ ".$1" = ".-r" ] || [ ".$1" = ".--recreate" ]; then
143
shtoolize -oshtool echo install mkdir path
146
if [ ".$1" = ".-d" ] || [ ".$1" = ".--debug" ]; then
150
name=`echo "$0" | sed -e 's;.*/\([^/]*\)$;\1;' -e 's;-sh$;;' -e 's;\.sh$;;'`
152
echo|install|mkdir|path )
153
# implicit tool command selection
157
# explicit tool command selection
167
## DISPATCH INTO SCRIPT PROLOG
173
str_usage="[-n|--newline] [-e|--expand] [<string> ...]"
176
opt_alias="n:newline,e:expand"
182
str_usage="[-v|--verbose] [-t|--trace] [-d|--mkdir] [-c|--copy] [-C|--compare-copy] [-s|--strip] [-m|--mode <mode>] [-o|--owner <owner>] [-g|--group <group>] [-e|--exec <sed-cmd>] <file> [<file> ...] <path>"
184
opt_spec="v.t.d.c.C.s.m:o:g:e+"
185
opt_alias="v:verbose,t:trace,d:mkdir,c:copy,C:compare-copy,s:strip,m:mode,o:owner,g:group,e:exec"
199
str_usage="[-t|--trace] [-f|--force] [-p|--parents] [-m|--mode <mode>] [-o|--owner <owner>] [-g|--group <group>] <dir> [<dir> ...]"
201
opt_spec="t.f.p.m:o:g:"
202
opt_alias="t:trace,f:force,p:parents,m:mode,o:owner,g:group"
212
str_usage="[-s|--suppress] [-r|--reverse] [-d|--dirname] [-b|--basename] [-m|--magic] [-p|--path <path>] <str> [<str> ...]"
215
opt_spec="s.r.d.b.m.p:"
216
opt_alias="s:suppress,r:reverse,d:dirname,b:basename,m:magic,p:path"
225
echo "$0:Error: unknown option \`$tool'" 2>&1
226
echo "$0:Hint: run \`$0 -h' for usage" 2>&1
230
echo "$0:Error: unknown command \`$tool'" 2>&1
231
echo "$0:Hint: run \`$0 -h' for usage" 2>&1
237
## COMMON UTILITY CODE
240
# commonly used ASCII values
245
# determine name of tool
246
if [ ".$tool" != . ]; then
247
# used inside shtool script
249
toolcmdhelp="shtool $tool"
250
msgprefix="shtool:$tool"
252
# used as standalone script
255
msgprefix="$str_tool"
258
# parse argument specification string
259
eval `echo $arg_spec |\
260
sed -e 's/^\([0-9]*\)\([+=]\)/arg_NUMS=\1; arg_MODE=\2/'`
262
# parse option specification string
263
eval `echo h.$opt_spec |\
264
sed -e 's/\([a-zA-Z0-9]\)\([.:+]\)/opt_MODE_\1=\2;/g'`
266
# parse option alias string
267
eval `echo h:help,$opt_alias |\
268
sed -e 's/-/_/g' -e 's/\([a-zA-Z0-9]\):\([^,]*\),*/opt_ALIAS_\2=\1;/g'`
270
# interate over argument line
272
while [ $# -gt 0 ]; do
273
# special option stops processing
274
if [ ".$1" = ".--" ]; then
279
# determine option and argument
281
if [ ".$opt_PREV" != . ]; then
282
# merge previous seen option with argument
288
# split argument into option and argument
292
sed -e 's/^x--\([a-zA-Z0-9-]*\)=\(.*\)$/opt_OPT="\1";opt_ARG="\2"/'`
293
opt_STR=`echo $opt_OPT | sed -e 's/-/_/g'`
294
eval "opt_OPT=\${opt_ALIAS_${opt_STR}-${opt_OPT}}"
297
opt_OPT=`echo "x$1" | cut -c4-`
298
opt_STR=`echo $opt_OPT | sed -e 's/-/_/g'`
299
eval "opt_OPT=\${opt_ALIAS_${opt_STR}-${opt_OPT}}"
304
sed -e 's/^x-\([a-zA-Z0-9]\)/opt_OPT="\1";/' \
305
-e 's/";\(.*\)$/"; opt_ARG="\1"/'`
308
opt_OPT=`echo "x$1" | cut -c3-`
320
# determine whether option needs an argument
321
eval "opt_MODE=\$opt_MODE_${opt_OPT}"
322
if [ ".$opt_ARG" = . ] && [ ".$opt_ARG_OK" != .yes ]; then
323
if [ ".$opt_MODE" = ".:" ] || [ ".$opt_MODE" = ".+" ]; then
333
eval "opt_${opt_OPT}=yes"
336
# option with argument (multiple occurances override)
337
eval "opt_${opt_OPT}=\"\$opt_ARG\""
340
# option with argument (multiple occurances append)
341
eval "opt_${opt_OPT}=\"\$opt_${opt_OPT}\${ASC_NL}\$opt_ARG\""
344
echo "$msgprefix:Error: unknown option: \`$opt_OPT'" 1>&2
345
echo "$msgprefix:Hint: run \`$toolcmdhelp -h' or \`man shtool' for details" 1>&2
350
if [ ".$opt_PREV" != . ]; then
351
echo "$msgprefix:Error: missing argument to option \`$opt_PREV'" 1>&2
352
echo "$msgprefix:Hint: run \`$toolcmdhelp -h' or \`man shtool' for details" 1>&2
356
# process help option
357
if [ ".$opt_h" = .yes ]; then
358
echo "Usage: $toolcmdhelp $str_usage"
362
# complain about incorrect number of arguments
365
if [ $# -ne $arg_NUMS ]; then
366
echo "$msgprefix:Error: invalid number of arguments (exactly $arg_NUMS expected)" 1>&2
367
echo "$msgprefix:Hint: run \`$toolcmd -h' or \`man shtool' for details" 1>&2
372
if [ $# -lt $arg_NUMS ]; then
373
echo "$msgprefix:Error: invalid number of arguments (at least $arg_NUMS expected)" 1>&2
374
echo "$msgprefix:Hint: run \`$toolcmd -h' or \`man shtool' for details" 1>&2
380
# establish a temporary file on request
381
if [ ".$gen_tmpfile" = .yes ]; then
382
# create (explicitly) secure temporary directory
383
if [ ".$TMPDIR" != . ]; then
385
elif [ ".$TEMPDIR" != . ]; then
390
tmpdir="$tmpdir/.shtool.$$"
392
rm -rf "$tmpdir" >/dev/null 2>&1 || true
393
mkdir "$tmpdir" >/dev/null 2>&1
394
if [ $? -ne 0 ]; then
395
echo "$msgprefix:Error: failed to create temporary directory \`$tmpdir'" 1>&2
400
# create (implicitly) secure temporary file
401
tmpfile="$tmpdir/shtool.tmp"
405
# utility function: map string to lower case
407
echo "$1" | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'
410
# utility function: map string to upper case
412
echo "$1" | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
418
if [ ".$gen_tmpfile" = .yes ]; then
419
rm -rf "$tmpdir" >/dev/null 2>&1 || true
425
## DISPATCH INTO SCRIPT BODY
432
## echo -- Print string with optional construct expansion
433
## Copyright (c) 1998-2005 Ralf S. Engelschall <rse@engelschall.com>
438
# check for broken escape sequence expansion
440
bytes=`echo '\1' | wc -c | awk '{ printf("%s", $1); }'`
441
if [ ".$bytes" != .3 ]; then
442
bytes=`echo -E '\1' | wc -c | awk '{ printf("%s", $1); }'`
443
if [ ".$bytes" = .3 ]; then
448
# check for existing -n option (to suppress newline)
450
bytes=`echo -n 123 2>/dev/null | wc -c | awk '{ printf("%s", $1); }'`
451
if [ ".$bytes" = .3 ]; then
455
# determine terminal bold sequence
458
if [ ".$opt_e" = .yes ] && [ ".`echo $text | grep '%[Bb]'`" != . ]; then
460
# for the most important terminal types we directly know the sequences
461
xterm|xterm*|vt220|vt220*)
462
term_bold=`awk 'BEGIN { printf("%c%c%c%c", 27, 91, 49, 109); }' </dev/null 2>/dev/null`
463
term_norm=`awk 'BEGIN { printf("%c%c%c", 27, 91, 109); }' </dev/null 2>/dev/null`
466
term_bold=`awk 'BEGIN { printf("%c%c%c%c%c%c", 27, 91, 49, 109, 0, 0); }' </dev/null 2>/dev/null`
467
term_norm=`awk 'BEGIN { printf("%c%c%c%c%c", 27, 91, 109, 0, 0); }' </dev/null 2>/dev/null`
469
# for all others, we try to use a possibly existing `tput' or `tcout' utility
471
paths=`echo $PATH | sed -e 's/:/ /g'`
472
for tool in tput tcout; do
473
for dir in $paths; do
474
if [ -r "$dir/$tool" ]; then
475
for seq in bold md smso; do # 'smso' is last
476
bold="`$dir/$tool $seq 2>/dev/null`"
477
if [ ".$bold" != . ]; then
482
if [ ".$term_bold" != . ]; then
483
for seq in sgr0 me rmso init reset; do # 'reset' is last
484
norm="`$dir/$tool $seq 2>/dev/null`"
485
if [ ".$norm" != . ]; then
494
if [ ".$term_bold" != . ] && [ ".$term_norm" != . ]; then
500
if [ ".$term_bold" = . ] || [ ".$term_norm" = . ]; then
501
echo "$msgprefix:Warning: unable to determine terminal sequence for bold mode" 1>&2
507
# determine user name
509
if [ ".$opt_e" = .yes ] && [ ".`echo $text | grep '%[uUgG]'`" != . ]; then
510
username="`(id -un) 2>/dev/null`"
511
if [ ".$username" = . ]; then
512
str="`(id) 2>/dev/null`"
513
if [ ".`echo $str | grep '^uid[ ]*=[ ]*[0-9]*('`" != . ]; then
514
username=`echo $str | sed -e 's/^uid[ ]*=[ ]*[0-9]*(//' -e 's/).*$//'`
516
if [ ".$username" = . ]; then
518
if [ ".$username" = . ]; then
520
if [ ".$username" = . ]; then
521
username="`(whoami) 2>/dev/null |\
522
awk '{ printf("%s", $1); }'`"
523
if [ ".$username" = . ]; then
524
username="`(who am i) 2>/dev/null |\
525
awk '{ printf("%s", $1); }'`"
526
if [ ".$username" = . ]; then
538
if [ ".$opt_e" = .yes ] && [ ".`echo $text | grep '%U'`" != . ]; then
539
userid="`(id -u) 2>/dev/null`"
540
if [ ".$userid" = . ]; then
541
userid="`(id -u ${username}) 2>/dev/null`"
542
if [ ".$userid" = . ]; then
543
str="`(id) 2>/dev/null`"
544
if [ ".`echo $str | grep '^uid[ ]*=[ ]*[0-9]*('`" != . ]; then
545
userid=`echo $str | sed -e 's/^uid[ ]*=[ ]*//' -e 's/(.*$//'`
547
if [ ".$userid" = . ]; then
548
userid=`(getent passwd ${username}) 2>/dev/null | \
549
sed -e 's/[^:]*:[^:]*://' -e 's/:.*$//'`
550
if [ ".$userid" = . ]; then
551
userid=`grep "^${username}:" /etc/passwd 2>/dev/null | \
552
sed -e 's/[^:]*:[^:]*://' -e 's/:.*$//'`
553
if [ ".$userid" = . ]; then
554
userid=`(ypcat passwd) 2>/dev/null |
555
grep "^${username}:" | \
556
sed -e 's/[^:]*:[^:]*://' -e 's/:.*$//'`
557
if [ ".$userid" = . ]; then
567
# determine (primary) group id
569
if [ ".$opt_e" = .yes ] && [ ".`echo $text | grep '%[gG]'`" != . ]; then
570
groupid="`(id -g ${username}) 2>/dev/null`"
571
if [ ".$groupid" = . ]; then
572
str="`(id) 2>/dev/null`"
573
if [ ".`echo $str | grep 'gid[ ]*=[ ]*[0-9]*('`" != . ]; then
574
groupid=`echo $str | sed -e 's/^.*gid[ ]*=[ ]*//' -e 's/(.*$//'`
576
if [ ".$groupid" = . ]; then
577
groupid=`(getent passwd ${username}) 2>/dev/null | \
578
sed -e 's/[^:]*:[^:]*:[^:]*://' -e 's/:.*$//'`
579
if [ ".$groupid" = . ]; then
580
groupid=`grep "^${username}:" /etc/passwd 2>/dev/null | \
581
sed -e 's/[^:]*:[^:]*:[^:]*://' -e 's/:.*$//'`
582
if [ ".$groupid" = . ]; then
583
groupid=`(ypcat passwd) 2>/dev/null | grep "^${username}:" | \
584
sed -e 's/[^:]*:[^:]*:[^:]*://' -e 's/:.*$//'`
585
if [ ".$groupid" = . ]; then
594
# determine (primary) group name
596
if [ ".$opt_e" = .yes ] && [ ".`echo $text | grep '%g'`" != . ]; then
597
groupname="`(id -gn ${username}) 2>/dev/null`"
598
if [ ".$groupname" = . ]; then
599
str="`(id) 2>/dev/null`"
600
if [ ".`echo $str | grep 'gid[ ]*=[ ]*[0-9]*('`" != . ]; then
601
groupname=`echo $str | sed -e 's/^.*gid[ ]*=[ ]*[0-9]*(//' -e 's/).*$//'`
603
if [ ".$groupname" = . ]; then
604
groupname=`(getent group) 2>/dev/null | \
605
grep "^[^:]*:[^:]*:${groupid}:" | \
607
if [ ".$groupname" = . ]; then
608
groupname=`grep "^[^:]*:[^:]*:${groupid}:" /etc/group 2>/dev/null | \
610
if [ ".$groupname" = . ]; then
611
groupname=`(ypcat group) 2>/dev/null | \
612
grep "^[^:]*:[^:]*:${groupid}:" | \
614
if [ ".$groupname" = . ]; then
623
# determine host and domain name
626
if [ ".$opt_e" = .yes ] && [ ".`echo $text | grep '%h'`" != . ]; then
627
hostname="`(uname -n) 2>/dev/null |\
628
awk '{ printf("%s", $1); }'`"
629
if [ ".$hostname" = . ]; then
630
hostname="`(hostname) 2>/dev/null |\
631
awk '{ printf("%s", $1); }'`"
632
if [ ".$hostname" = . ]; then
638
domainname=".`echo $hostname | cut -d. -f2-`"
639
hostname="`echo $hostname | cut -d. -f1`"
643
if [ ".$opt_e" = .yes ] && [ ".`echo $text | grep '%d'`" != . ]; then
644
if [ ".$domainname" = . ]; then
645
if [ -f /etc/resolv.conf ]; then
646
domainname="`grep '^[ ]*domain' /etc/resolv.conf | sed -e 'q' |\
647
sed -e 's/.*domain//' \
648
-e 's/^[ ]*//' -e 's/^ *//' -e 's/^ *//' \
649
-e 's/^\.//' -e 's/^/./' |\
650
awk '{ printf("%s", $1); }'`"
651
if [ ".$domainname" = . ]; then
652
domainname="`grep '^[ ]*search' /etc/resolv.conf | sed -e 'q' |\
653
sed -e 's/.*search//' \
654
-e 's/^[ ]*//' -e 's/^ *//' -e 's/^ *//' \
655
-e 's/ .*//' -e 's/ .*//' \
656
-e 's/^\.//' -e 's/^/./' |\
657
awk '{ printf("%s", $1); }'`"
663
# determine current time
668
if [ ".$opt_e" = .yes ] && [ ".`echo $text | grep '%[DMYm]'`" != . ]; then
669
time_day=`date '+%d'`
670
time_month=`date '+%m'`
671
time_year=`date '+%Y' 2>/dev/null`
672
if [ ".$time_year" = . ]; then
673
time_year=`date '+%y'`
675
[5-9][0-9]) time_year="19$time_year" ;;
676
[0-4][0-9]) time_year="20$time_year" ;;
680
1|01) time_monthname='Jan' ;;
681
2|02) time_monthname='Feb' ;;
682
3|03) time_monthname='Mar' ;;
683
4|04) time_monthname='Apr' ;;
684
5|05) time_monthname='May' ;;
685
6|06) time_monthname='Jun' ;;
686
7|07) time_monthname='Jul' ;;
687
8|08) time_monthname='Aug' ;;
688
9|09) time_monthname='Sep' ;;
689
10) time_monthname='Oct' ;;
690
11) time_monthname='Nov' ;;
691
12) time_monthname='Dec' ;;
695
# expand special ``%x'' constructs
696
if [ ".$opt_e" = .yes ]; then
697
text=`echo $seo "$text" |\
698
sed -e "s/%B/${term_bold}/g" \
699
-e "s/%b/${term_norm}/g" \
700
-e "s/%u/${username}/g" \
701
-e "s/%U/${userid}/g" \
702
-e "s/%g/${groupname}/g" \
703
-e "s/%G/${groupid}/g" \
704
-e "s/%h/${hostname}/g" \
705
-e "s/%d/${domainname}/g" \
706
-e "s/%D/${time_day}/g" \
707
-e "s/%M/${time_month}/g" \
708
-e "s/%Y/${time_year}/g" \
709
-e "s/%m/${time_monthname}/g" 2>/dev/null`
713
if [ .$opt_n = .no ]; then
716
# the harder part: echo -n is best, because
717
# awk may complain about some \xx sequences.
718
if [ ".$minusn" != . ]; then
719
echo $seo $minusn "$text"
721
echo dummy | awk '{ printf("%s", TEXT); }' TEXT="$text"
730
## install -- Install a program, script or datafile
731
## Copyright (c) 1997-2005 Ralf S. Engelschall <rse@engelschall.com>
734
# special case: "shtool install -d <dir> [...]" internally
735
# maps to "shtool mkdir -f -p -m 755 <dir> [...]"
736
if [ "$opt_d" = yes ]; then
737
cmd="$0 mkdir -f -p -m 755"
738
if [ ".$opt_o" != . ]; then
739
cmd="$cmd -o '$opt_o'"
741
if [ ".$opt_g" != . ]; then
742
cmd="$cmd -g '$opt_g'"
744
if [ ".$opt_v" = .yes ]; then
747
if [ ".$opt_t" = .yes ]; then
751
eval "$cmd $dir" || shtool_exit $?
756
# determine source(s) and destination
759
while [ $# -gt 1 ]; do
765
# type check for destination
767
if [ -d $dstpath ]; then
768
dstpath=`echo "$dstpath" | sed -e 's:/$::'`
772
# consistency check for destination
773
if [ $argc -gt 2 ] && [ $dstisdir = 0 ]; then
774
echo "$msgprefix:Error: multiple sources require destination to be directory" 1>&2
778
# iterate over all source(s)
782
# if destination is a directory, append the input filename
783
if [ $dstisdir = 1 ]; then
784
dstfile=`echo "$src" | sed -e 's;.*/\([^/]*\)$;\1;'`
788
# check for correct arguments
789
if [ ".$src" = ".$dst" ]; then
790
echo "$msgprefix:Warning: source and destination are the same - skipped" 1>&2
793
if [ -d "$src" ]; then
794
echo "$msgprefix:Warning: source \`$src' is a directory - skipped" 1>&2
798
# make a temp file name in the destination directory
800
sed -e 's;[^/]*$;;' -e 's;\(.\)/$;\1;' -e 's;^$;.;' \
801
-e "s;\$;/#INST@$$#;"`
804
if [ ".$opt_v" = .yes ]; then
805
echo "$src -> $dst" 1>&2
808
# copy or move the file name to the temp name
809
# (because we might be not allowed to change the source)
810
if [ ".$opt_C" = .yes ]; then
813
if [ ".$opt_c" = .yes ]; then
814
if [ ".$opt_t" = .yes ]; then
815
echo "cp $src $dsttmp" 1>&2
817
cp $src $dsttmp || shtool_exit $?
819
if [ ".$opt_t" = .yes ]; then
820
echo "mv $src $dsttmp" 1>&2
822
mv $src $dsttmp || shtool_exit $?
825
# adjust the target file
826
if [ ".$opt_e" != . ]; then
828
OIFS="$IFS"; IFS="$ASC_NL"; set -- $opt_e; IFS="$OIFS"
833
cp $dsttmp $dsttmp.old
835
eval "$sed <$dsttmp.old >$dsttmp" || shtool_exit $?
838
if [ ".$opt_s" = .yes ]; then
839
if [ ".$opt_t" = .yes ]; then
840
echo "strip $dsttmp" 1>&2
842
strip $dsttmp || shtool_exit $?
844
if [ ".$opt_o" != . ]; then
845
if [ ".$opt_t" = .yes ]; then
846
echo "chown $opt_o $dsttmp" 1>&2
848
chown $opt_o $dsttmp || shtool_exit $?
850
if [ ".$opt_g" != . ]; then
851
if [ ".$opt_t" = .yes ]; then
852
echo "chgrp $opt_g $dsttmp" 1>&2
854
chgrp $opt_g $dsttmp || shtool_exit $?
856
if [ ".$opt_m" != ".-" ]; then
857
if [ ".$opt_t" = .yes ]; then
858
echo "chmod $opt_m $dsttmp" 1>&2
860
chmod $opt_m $dsttmp || shtool_exit $?
863
# determine whether to do a quick install
864
# (has to be done _after_ the strip was already done)
866
if [ ".$opt_C" = .yes ]; then
868
if cmp -s $src $dst; then
874
# finally, install the file to the real destination
875
if [ $quick = yes ]; then
876
if [ ".$opt_t" = .yes ]; then
877
echo "rm -f $dsttmp" 1>&2
881
if [ ".$opt_t" = .yes ]; then
882
echo "rm -f $dst && mv $dsttmp $dst" 1>&2
884
rm -f $dst && mv $dsttmp $dst
893
## mkdir -- Make one or more directories
894
## Copyright (c) 1996-2005 Ralf S. Engelschall <rse@engelschall.com>
898
for p in ${1+"$@"}; do
899
# if the directory already exists...
901
if [ ".$opt_f" = .no ] && [ ".$opt_p" = .no ]; then
902
echo "$msgprefix:Error: directory already exists: $p" 1>&2
909
# if the directory has to be created...
910
if [ ".$opt_p" = .no ]; then
911
if [ ".$opt_t" = .yes ]; then
914
mkdir $p || errstatus=$?
915
if [ ".$opt_o" != . ]; then
916
if [ ".$opt_t" = .yes ]; then
917
echo "chown $opt_o $p" 1>&2
919
chown $opt_o $p || errstatus=$?
921
if [ ".$opt_g" != . ]; then
922
if [ ".$opt_t" = .yes ]; then
923
echo "chgrp $opt_g $p" 1>&2
925
chgrp $opt_g $p || errstatus=$?
927
if [ ".$opt_m" != . ]; then
928
if [ ".$opt_t" = .yes ]; then
929
echo "chmod $opt_m $p" 1>&2
931
chmod $opt_m $p || errstatus=$?
934
# the smart situation
935
set fnord `echo ":$p" |\
942
for d in ${1+"$@"}; do
943
pathcomp="$pathcomp$d"
945
-* ) pathcomp="./$pathcomp" ;;
947
if [ ! -d "$pathcomp" ]; then
948
if [ ".$opt_t" = .yes ]; then
949
echo "mkdir $pathcomp" 1>&2
951
mkdir $pathcomp || errstatus=$?
952
if [ ".$opt_o" != . ]; then
953
if [ ".$opt_t" = .yes ]; then
954
echo "chown $opt_o $pathcomp" 1>&2
956
chown $opt_o $pathcomp || errstatus=$?
958
if [ ".$opt_g" != . ]; then
959
if [ ".$opt_t" = .yes ]; then
960
echo "chgrp $opt_g $pathcomp" 1>&2
962
chgrp $opt_g $pathcomp || errstatus=$?
964
if [ ".$opt_m" != . ]; then
965
if [ ".$opt_t" = .yes ]; then
966
echo "chmod $opt_m $pathcomp" 1>&2
968
chmod $opt_m $pathcomp || errstatus=$?
971
pathcomp="$pathcomp/"
976
shtool_exit $errstatus
981
## path -- Deal with program paths
982
## Copyright (c) 1998-2005 Ralf S. Engelschall <rse@engelschall.com>
987
# check whether the test command supports the -x option
988
if [ -x /bin/sh ] 2>/dev/null; then
995
paths="`echo $opt_p |\
1002
# translate forward to reverse path
1003
if [ ".$opt_r" = .yes ]; then
1004
if [ "x$namelist" = "x." ]; then
1008
for pe in `IFS="$IFS/"; echo $namelist`; do
1012
echo $rp | sed -e 's:/$::'
1017
# strip out directory or base name
1018
if [ ".$opt_d" = .yes ]; then
1020
sed -e 's;[^/]*$;;' -e 's;\(.\)/$;\1;'
1023
if [ ".$opt_b" = .yes ]; then
1025
sed -e 's;.*/\([^/]*\)$;\1;'
1030
# Perl Interpreter (perl)
1031
if [ ".$opt_m" = .yes ] && [ ".$namelist" = .perl ]; then
1032
rm -f $tmpfile >/dev/null 2>&1
1036
for dir in $paths; do
1037
dir=`echo $dir | sed -e 's;/*$;;'`
1039
for name in perl perl5 miniperl; do
1040
if [ $minusx "$dir/$name" ] && [ ! -d "$dir/$name" ]; then
1042
pv=`$perl -e 'printf("%.3f", $]);'`
1043
echo "$pv:$pc:$nc:$perl" >>$tmpfile
1050
if [ $found = 1 ]; then
1051
perl="`cat $tmpfile | sort -r -u | sed -e 'q' | cut -d: -f4`"
1052
rm -f $tmpfile >/dev/null 2>&1
1056
rm -f $tmpfile >/dev/null 2>&1
1061
# C pre-processor (cpp)
1062
if [ ".$opt_m" = .yes ] && [ ".$namelist" = .cpp ]; then
1063
echo >$tmpfile.c "#include <assert.h>"
1064
echo >>$tmpfile.c "Syntax Error"
1065
# 1. try the standard cc -E approach
1067
(eval "$cpp $tmpfile.c >/dev/null") 2>$tmpfile.out
1068
my_error=`grep -v '^ *+' $tmpfile.out`
1069
if [ ".$my_error" != . ]; then
1070
# 2. try the cc -E approach and GCC's -traditional-ccp option
1071
cpp="${CC-cc} -E -traditional-cpp"
1072
(eval "$cpp $tmpfile.c >/dev/null") 2>$tmpfile.out
1073
my_error=`grep -v '^ *+' $tmpfile.out`
1074
if [ ".$my_error" != . ]; then
1075
# 3. try a standalone cpp command in path and lib dirs
1076
for path in $paths /lib /usr/lib /usr/local/lib; do
1077
path=`echo $path | sed -e 's;/*$;;'`
1078
if [ $minusx "$path/cpp" ] && [ ! -d "$path/cpp" ]; then
1083
if [ ".$cpp" != . ]; then
1084
(eval "$cpp $tmpfile.c >/dev/null") 2>$tmpfile.out
1085
my_error=`grep -v '^ *+' $tmpfile.out`
1086
if [ ".$my_error" != . ]; then
1093
rm -f $tmpfile >/dev/null 2>&1
1094
rm -f $tmpfile.c $tmpfile.out >/dev/null 2>&1
1095
if [ ".$cpp" != . ]; then
1102
# STANDARD SITUATION
1103
# iterate over names
1104
for name in $namelist; do
1105
# iterate over paths
1106
for path in $paths; do
1107
path=`echo $path | sed -e 's;/*$;;'`
1108
if [ $minusx "$path/$name" ] && [ ! -d "$path/$name" ]; then
1109
if [ ".$opt_s" != .yes ]; then