1#!/bin/sh
2##
3##  GNU shtool -- The GNU Portable Shell Tool
4##  Copyright (c) 1994-2005 Ralf S. Engelschall <rse@engelschall.com>
5##
6##  See http://www.gnu.org/software/shtool/ for more information.
7##  See ftp://ftp.gnu.org/gnu/shtool/ for latest version.
8##
9##  Version:  2.0.3 (02-Oct-2005)
10##  Contents: 6/19 available modules
11##
12
13##
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.
18##
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.
23##
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>.
28##
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.
35##
36
37##
38##  Usage: shtool [<options>] [<cmd-name> [<cmd-options>] [<cmd-args>]]
39##
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##    fixperm    Fix file permissions inside a source tree
45##    tarball    Roll distribution tarballs
46##    version    Maintain a version information file
47##
48##  Not available commands (because module was not built-in):
49##    mdate      Pretty-print modification time of a file or dir
50##    table      Pretty-print a field-separated list as a table
51##    prop       Display progress with a running propeller
52##    move       Move files with simultaneous substitution
53##    mkln       Make link with calculation of relative paths
54##    mkshadow   Make a shadow tree through symbolic links
55##    rotate     Logfile rotation
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##    path       Deal with program paths
62##
63
64if [ $# -eq 0 ]; then
65    echo "$0:Error: invalid command line" 1>&2
66    echo "$0:Hint:  run \`$0 -h' for usage" 1>&2
67    exit 1
68fi
69if [ ".$1" = ".-h" ] || [ ".$1" = ".--help" ]; then
70    echo "This is GNU shtool, version 2.0.3 (02-Oct-2005)"
71    echo "Copyright (c) 1994-2005 Ralf S. Engelschall <rse@engelschall.com>"
72    echo "Report bugs to <bug-shtool@gnu.org>"
73    echo ''
74    echo "Usage: shtool [<options>] [<cmd-name> [<cmd-options>] [<cmd-args>]]"
75    echo ''
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'
81    echo ''
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>'
90    echo '           [<dir> ...]'
91    echo '  fixperm  [-v|--verbose] [-t|--trace] <path> [<path> ...]'
92    echo '  tarball  [-t|--trace] [-v|--verbose] [-o|--output <tarball>]'
93    echo '           [-c|--compress <prog>] [-d|--directory <dir>] [-u|--user'
94    echo '           <user>] [-g|--group <group>] [-e|--exclude <pattern>]'
95    echo '           <path> [<path> ...]'
96    echo '  version  [-l|--language <lang>] [-n|--name <name>] [-p|--prefix'
97    echo '           <prefix>] [-s|--set <version>] [-e|--edit] [-i|--increase'
98    echo '           <knob>] [-d|--display <type>] <file>'
99    echo ''
100    echo 'Not available <cmd-name> (because module was not built-in):'
101    echo '  mdate    [-n|--newline] [-z|--zero] [-s|--shorten] [-d|--digits]'
102    echo '           [-f|--field-sep <str>] [-o|--order <spec>] <path>'
103    echo '  table    [-F|--field-sep <sep>] [-w|--width <width>] [-c|--columns'
104    echo '           <cols>] [-s|--strip <strip>] <str><sep><str>...'
105    echo '  prop     [-p|--prefix <str>]'
106    echo '  move     [-v|--verbose] [-t|--trace] [-e|--expand] [-p|--preserve]'
107    echo '           <src-file> <dst-file>'
108    echo '  mkln     [-t|--trace] [-f|--force] [-s|--symbolic] <src-path>'
109    echo '           [<src-path> ...] <dst-path>'
110    echo '  mkshadow [-v|--verbose] [-t|--trace] [-a|--all] <src-dir> <dst-dir>'
111    echo '  rotate   [-v|--verbose] [-t|--trace] [-f|--force] [-n|--num-files'
112    echo '           <count>] [-s|--size <size>] [-c|--copy] [-r|--remove]'
113    echo '           [-a|--archive-dir <dir>] [-z|--compress [<tool>:]<level>]'
114    echo '           [-b|--background] [-d|--delay] [-p|--pad <len>] [-m|--mode'
115    echo '           <mode>] [-o|--owner <owner>] [-g|--group <group>] [-M|--migrate'
116    echo '           <cmd>] [-P|--prolog <cmd>] [-E|--epilog <cmd>] <file> [...]'
117    echo '  subst    [-v|--verbose] [-t|--trace] [-n|--nop] [-w|--warning]'
118    echo '           [-q|--quiet] [-s|--stealth] [-i|--interactive] [-b|--backup'
119    echo '           <ext>] [-e|--exec <cmd>] [-f|--file <cmd-file>] [<file>]'
120    echo '           [...]'
121    echo '  platform [-F|--format <format>] [-S|--sep <string>] [-C|--conc'
122    echo '           <string>] [-L|--lower] [-U|--upper] [-v|--verbose]'
123    echo '           [-c|--concise] [-n|--no-newline] [-t|--type <type>]'
124    echo '           [-V|--version] [-h|--help]'
125    echo '  arx      [-t|--trace] [-C|--command <cmd>] <op> <archive> [<file>'
126    echo '           ...]'
127    echo '  slo      [-p|--prefix <str>] -- -L<dir> -l<lib> [-L<dir> -l<lib>'
128    echo '           ...]'
129    echo '  scpp     [-v|--verbose] [-p|--preserve] [-f|--filter <filter>]'
130    echo '           [-o|--output <ofile>] [-t|--template <tfile>] [-M|--mark'
131    echo '           <mark>] [-D|--define <dname>] [-C|--class <cname>]'
132    echo '           <file> [<file> ...]'
133    echo '  path     [-s|--suppress] [-r|--reverse] [-d|--dirname] [-b|--basename]'
134    echo '           [-m|--magic] [-p|--path <path>] <str> [<str> ...]'
135    echo ''
136    exit 0
137fi
138if [ ".$1" = ".-v" ] || [ ".$1" = ".--version" ]; then
139    echo "GNU shtool 2.0.3 (02-Oct-2005)"
140    exit 0
141fi
142if [ ".$1" = ".-r" ] || [ ".$1" = ".--recreate" ]; then
143    shtoolize -oshtool echo install mkdir fixperm tarball version
144    exit 0
145fi
146if [ ".$1" = ".-d" ] || [ ".$1" = ".--debug" ]; then
147    shift
148    set -x
149fi
150name=`echo "$0" | sed -e 's;.*/\([^/]*\)$;\1;' -e 's;-sh$;;' -e 's;\.sh$;;'`
151case "$name" in
152    echo|install|mkdir|fixperm|tarball|version )
153        #   implicit tool command selection
154        tool="$name"
155        ;;
156    * )
157        #   explicit tool command selection
158        tool="$1"
159        shift
160        ;;
161esac
162arg_spec=""
163opt_spec=""
164gen_tmpfile=no
165
166##
167##  DISPATCH INTO SCRIPT PROLOG
168##
169
170case $tool in
171    echo )
172        str_tool="echo"
173        str_usage="[-n|--newline] [-e|--expand] [<string> ...]"
174        arg_spec="0+"
175        opt_spec="n.e."
176        opt_alias="n:newline,e:expand"
177        opt_n=no
178        opt_e=no
179        ;;
180    install )
181        str_tool="install"
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>"
183        arg_spec="1+"
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"
186        opt_v=no
187        opt_t=no
188        opt_d=no
189        opt_c=no
190        opt_C=no
191        opt_s=no
192        opt_m="0755"
193        opt_o=""
194        opt_g=""
195        opt_e=""
196        ;;
197    mkdir )
198        str_tool="mkdir"
199        str_usage="[-t|--trace] [-f|--force] [-p|--parents] [-m|--mode <mode>] [-o|--owner <owner>] [-g|--group <group>] <dir> [<dir> ...]"
200        arg_spec="1+"
201        opt_spec="t.f.p.m:o:g:"
202        opt_alias="t:trace,f:force,p:parents,m:mode,o:owner,g:group"
203        opt_t=no
204        opt_f=no
205        opt_p=no
206        opt_m=""
207        opt_o=""
208        opt_g=""
209        ;;
210    fixperm )
211        str_tool="fixperm"
212        str_usage="[-v|--verbose] [-t|--trace] <path> [<path> ...]"
213        arg_spec="1+"
214        opt_spec="v.t."
215        opt_alias="v:verbose,t:trace"
216        opt_v=no
217        opt_t=no
218        ;;
219    tarball )
220        str_tool="tarball"
221        str_usage="[-t|--trace] [-v|--verbose] [-o|--output <tarball>] [-c|--compress <prog>] [-d|--directory <dir>] [-u|--user <user>] [-g|--group <group>] [-e|--exclude <pattern>] <path> [<path> ...]"
222        gen_tmpfile=yes
223        arg_spec="1+"
224        opt_spec="t.v.o:c:d:u:g:e:"
225        opt_alias="t:trace,v:verbose,o:output,c:compress,d:directory,u:user,g:group,e:exclude"
226        opt_t=no
227        opt_v=no
228        opt_o=""
229        opt_c=""
230        opt_d=""
231        opt_u=""
232        opt_g=""
233        opt_e="CVS,\\.cvsignore,\\.[oa]\$"
234        ;;
235    version )
236        str_tool="version"
237        str_usage="[-l|--language <lang>] [-n|--name <name>] [-p|--prefix <prefix>] [-s|--set <version>] [-e|--edit] [-i|--increase <knob>] [-d|--display <type>] <file>"
238        arg_spec="1="
239        opt_spec="l:n:p:s:i:e.d:"
240        opt_alias="l:language,n:name,p:prefix,s:set,e:edit,i:increase,d:display"
241        opt_l="txt"
242        opt_n="unknown"
243        opt_p=""
244        opt_s=""
245        opt_e="no"
246        opt_i=""
247        opt_d="short"
248        ;;
249    -* )
250        echo "$0:Error: unknown option \`$tool'" 2>&1
251        echo "$0:Hint:  run \`$0 -h' for usage" 2>&1
252        exit 1
253        ;;
254    * )
255        echo "$0:Error: unknown command \`$tool'" 2>&1
256        echo "$0:Hint:  run \`$0 -h' for usage" 2>&1
257        exit 1
258        ;;
259esac
260
261##
262##  COMMON UTILITY CODE
263##
264
265#   commonly used ASCII values
266ASC_TAB="	"
267ASC_NL="
268"
269
270#   determine name of tool
271if [ ".$tool" != . ]; then
272    #   used inside shtool script
273    toolcmd="$0 $tool"
274    toolcmdhelp="shtool $tool"
275    msgprefix="shtool:$tool"
276else
277    #   used as standalone script
278    toolcmd="$0"
279    toolcmdhelp="sh $0"
280    msgprefix="$str_tool"
281fi
282
283#   parse argument specification string
284eval `echo $arg_spec |\
285      sed -e 's/^\([0-9]*\)\([+=]\)/arg_NUMS=\1; arg_MODE=\2/'`
286
287#   parse option specification string
288eval `echo h.$opt_spec |\
289      sed -e 's/\([a-zA-Z0-9]\)\([.:+]\)/opt_MODE_\1=\2;/g'`
290
291#   parse option alias string
292eval `echo h:help,$opt_alias |\
293      sed -e 's/-/_/g' -e 's/\([a-zA-Z0-9]\):\([^,]*\),*/opt_ALIAS_\2=\1;/g'`
294
295#   interate over argument line
296opt_PREV=''
297while [ $# -gt 0 ]; do
298    #   special option stops processing
299    if [ ".$1" = ".--" ]; then
300        shift
301        break
302    fi
303
304    #   determine option and argument
305    opt_ARG_OK=no
306    if [ ".$opt_PREV" != . ]; then
307        #   merge previous seen option with argument
308        opt_OPT="$opt_PREV"
309        opt_ARG="$1"
310        opt_ARG_OK=yes
311        opt_PREV=''
312    else
313        #   split argument into option and argument
314        case "$1" in
315            --[a-zA-Z0-9]*=*)
316                eval `echo "x$1" |\
317                      sed -e 's/^x--\([a-zA-Z0-9-]*\)=\(.*\)$/opt_OPT="\1";opt_ARG="\2"/'`
318                opt_STR=`echo $opt_OPT | sed -e 's/-/_/g'`
319                eval "opt_OPT=\${opt_ALIAS_${opt_STR}-${opt_OPT}}"
320                ;;
321            --[a-zA-Z0-9]*)
322                opt_OPT=`echo "x$1" | cut -c4-`
323                opt_STR=`echo $opt_OPT | sed -e 's/-/_/g'`
324                eval "opt_OPT=\${opt_ALIAS_${opt_STR}-${opt_OPT}}"
325                opt_ARG=''
326                ;;
327            -[a-zA-Z0-9]*)
328                eval `echo "x$1" |\
329                      sed -e 's/^x-\([a-zA-Z0-9]\)/opt_OPT="\1";/' \
330                          -e 's/";\(.*\)$/"; opt_ARG="\1"/'`
331                ;;
332            -[a-zA-Z0-9])
333                opt_OPT=`echo "x$1" | cut -c3-`
334                opt_ARG=''
335                ;;
336            *)
337                break
338                ;;
339        esac
340    fi
341
342    #   eat up option
343    shift
344
345    #   determine whether option needs an argument
346    eval "opt_MODE=\$opt_MODE_${opt_OPT}"
347    if [ ".$opt_ARG" = . ] && [ ".$opt_ARG_OK" != .yes ]; then
348        if [ ".$opt_MODE" = ".:" ] || [ ".$opt_MODE" = ".+" ]; then
349            opt_PREV="$opt_OPT"
350            continue
351        fi
352    fi
353
354    #   process option
355    case $opt_MODE in
356        '.' )
357            #   boolean option
358            eval "opt_${opt_OPT}=yes"
359            ;;
360        ':' )
361            #   option with argument (multiple occurances override)
362            eval "opt_${opt_OPT}=\"\$opt_ARG\""
363            ;;
364        '+' )
365            #   option with argument (multiple occurances append)
366            eval "opt_${opt_OPT}=\"\$opt_${opt_OPT}\${ASC_NL}\$opt_ARG\""
367            ;;
368        * )
369            echo "$msgprefix:Error: unknown option: \`$opt_OPT'" 1>&2
370            echo "$msgprefix:Hint:  run \`$toolcmdhelp -h' or \`man shtool' for details" 1>&2
371            exit 1
372            ;;
373    esac
374done
375if [ ".$opt_PREV" != . ]; then
376    echo "$msgprefix:Error: missing argument to option \`$opt_PREV'" 1>&2
377    echo "$msgprefix:Hint:  run \`$toolcmdhelp -h' or \`man shtool' for details" 1>&2
378    exit 1
379fi
380
381#   process help option
382if [ ".$opt_h" = .yes ]; then
383    echo "Usage: $toolcmdhelp $str_usage"
384    exit 0
385fi
386
387#   complain about incorrect number of arguments
388case $arg_MODE in
389    '=' )
390        if [ $# -ne $arg_NUMS ]; then
391            echo "$msgprefix:Error: invalid number of arguments (exactly $arg_NUMS expected)" 1>&2
392            echo "$msgprefix:Hint:  run \`$toolcmd -h' or \`man shtool' for details" 1>&2
393            exit 1
394        fi
395        ;;
396    '+' )
397        if [ $# -lt $arg_NUMS ]; then
398            echo "$msgprefix:Error: invalid number of arguments (at least $arg_NUMS expected)" 1>&2
399            echo "$msgprefix:Hint:  run \`$toolcmd -h' or \`man shtool' for details" 1>&2
400            exit 1
401        fi
402        ;;
403esac
404
405#   establish a temporary file on request
406if [ ".$gen_tmpfile" = .yes ]; then
407    #   create (explicitly) secure temporary directory
408    if [ ".$TMPDIR" != . ]; then
409        tmpdir="$TMPDIR"
410    elif [ ".$TEMPDIR" != . ]; then
411        tmpdir="$TEMPDIR"
412    else
413        tmpdir="/tmp"
414    fi
415    tmpdir="$tmpdir/.shtool.$$"
416    ( umask 077
417      rm -rf "$tmpdir" >/dev/null 2>&1 || true
418      mkdir  "$tmpdir" >/dev/null 2>&1
419      if [ $? -ne 0 ]; then
420          echo "$msgprefix:Error: failed to create temporary directory \`$tmpdir'" 1>&2
421          exit 1
422      fi
423    )
424
425    #   create (implicitly) secure temporary file
426    tmpfile="$tmpdir/shtool.tmp"
427    touch "$tmpfile"
428fi
429
430#   utility function: map string to lower case
431util_lower () {
432    echo "$1" | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'
433}
434
435#   utility function: map string to upper case
436util_upper () {
437    echo "$1" | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
438}
439
440#   cleanup procedure
441shtool_exit () {
442    rc="$1"
443    if [ ".$gen_tmpfile" = .yes ]; then
444        rm -rf "$tmpdir" >/dev/null 2>&1 || true
445    fi
446    exit $rc
447}
448
449##
450##  DISPATCH INTO SCRIPT BODY
451##
452
453case $tool in
454
455echo )
456    ##
457    ##  echo -- Print string with optional construct expansion
458    ##  Copyright (c) 1998-2005 Ralf S. Engelschall <rse@engelschall.com>
459    ##
460
461    text="$*"
462
463    #   check for broken escape sequence expansion
464    seo=''
465    bytes=`echo '\1' | wc -c | awk '{ printf("%s", $1); }'`
466    if [ ".$bytes" != .3 ]; then
467        bytes=`echo -E '\1' | wc -c | awk '{ printf("%s", $1); }'`
468        if [ ".$bytes" = .3 ]; then
469            seo='-E'
470        fi
471    fi
472
473    #   check for existing -n option (to suppress newline)
474    minusn=''
475    bytes=`echo -n 123 2>/dev/null | wc -c | awk '{ printf("%s", $1); }'`
476    if [ ".$bytes" = .3 ]; then
477        minusn='-n'
478    fi
479
480    #   determine terminal bold sequence
481    term_bold=''
482    term_norm=''
483    if [ ".$opt_e" = .yes ] && [ ".`echo $text | grep '%[Bb]'`" != . ]; then
484        case $TERM in
485            #   for the most important terminal types we directly know the sequences
486            xterm|xterm*|vt220|vt220*)
487                term_bold=`awk 'BEGIN { printf("%c%c%c%c", 27, 91, 49, 109); }' </dev/null 2>/dev/null`
488                term_norm=`awk 'BEGIN { printf("%c%c%c", 27, 91, 109); }' </dev/null 2>/dev/null`
489                ;;
490            vt100|vt100*|cygwin)
491                term_bold=`awk 'BEGIN { printf("%c%c%c%c%c%c", 27, 91, 49, 109, 0, 0); }' </dev/null 2>/dev/null`
492                term_norm=`awk 'BEGIN { printf("%c%c%c%c%c", 27, 91, 109, 0, 0); }' </dev/null 2>/dev/null`
493                ;;
494            #   for all others, we try to use a possibly existing `tput' or `tcout' utility
495            * )
496                paths=`echo $PATH | sed -e 's/:/ /g'`
497                for tool in tput tcout; do
498                    for dir in $paths; do
499                        if [ -r "$dir/$tool" ]; then
500                            for seq in bold md smso; do # 'smso' is last
501                                bold="`$dir/$tool $seq 2>/dev/null`"
502                                if [ ".$bold" != . ]; then
503                                    term_bold="$bold"
504                                    break
505                                fi
506                            done
507                            if [ ".$term_bold" != . ]; then
508                                for seq in sgr0 me rmso init reset; do # 'reset' is last
509                                    norm="`$dir/$tool $seq 2>/dev/null`"
510                                    if [ ".$norm" != . ]; then
511                                        term_norm="$norm"
512                                        break
513                                    fi
514                                done
515                            fi
516                            break
517                        fi
518                    done
519                    if [ ".$term_bold" != . ] && [ ".$term_norm" != . ]; then
520                        break;
521                    fi
522                done
523                ;;
524        esac
525        if [ ".$term_bold" = . ] || [ ".$term_norm" = . ]; then
526            echo "$msgprefix:Warning: unable to determine terminal sequence for bold mode" 1>&2
527            term_bold=''
528            term_norm=''
529        fi
530    fi
531
532    #   determine user name
533    username=''
534    if [ ".$opt_e" = .yes ] && [ ".`echo $text | grep '%[uUgG]'`" != . ]; then
535        username="`(id -un) 2>/dev/null`"
536        if [ ".$username" = . ]; then
537            str="`(id) 2>/dev/null`"
538            if [ ".`echo $str | grep '^uid[ 	]*=[ 	]*[0-9]*('`" != . ]; then
539                username=`echo $str | sed -e 's/^uid[ 	]*=[ 	]*[0-9]*(//' -e 's/).*$//'`
540            fi
541            if [ ".$username" = . ]; then
542                username="$LOGNAME"
543                if [ ".$username" = . ]; then
544                    username="$USER"
545                    if [ ".$username" = . ]; then
546                        username="`(whoami) 2>/dev/null |\
547                                   awk '{ printf("%s", $1); }'`"
548                        if [ ".$username" = . ]; then
549                            username="`(who am i) 2>/dev/null |\
550                                       awk '{ printf("%s", $1); }'`"
551                            if [ ".$username" = . ]; then
552                                username='unknown'
553                            fi
554                        fi
555                    fi
556                fi
557            fi
558        fi
559    fi
560
561    #   determine user id
562    userid=''
563    if [ ".$opt_e" = .yes ] && [ ".`echo $text | grep '%U'`" != . ]; then
564        userid="`(id -u) 2>/dev/null`"
565        if [ ".$userid" = . ]; then
566            userid="`(id -u ${username}) 2>/dev/null`"
567            if [ ".$userid" = . ]; then
568                str="`(id) 2>/dev/null`"
569                if [ ".`echo $str | grep '^uid[ 	]*=[ 	]*[0-9]*('`" != . ]; then
570                    userid=`echo $str | sed -e 's/^uid[ 	]*=[ 	]*//' -e 's/(.*$//'`
571                fi
572                if [ ".$userid" = . ]; then
573                    userid=`(getent passwd ${username}) 2>/dev/null | \
574                            sed -e 's/[^:]*:[^:]*://' -e 's/:.*$//'`
575                    if [ ".$userid" = . ]; then
576                        userid=`grep "^${username}:" /etc/passwd 2>/dev/null | \
577                                sed -e 's/[^:]*:[^:]*://' -e 's/:.*$//'`
578                        if [ ".$userid" = . ]; then
579                            userid=`(ypcat passwd) 2>/dev/null |
580                                    grep "^${username}:" | \
581                                    sed -e 's/[^:]*:[^:]*://' -e 's/:.*$//'`
582                            if [ ".$userid" = . ]; then
583                                userid='?'
584                            fi
585                        fi
586                    fi
587                fi
588            fi
589        fi
590    fi
591
592    #   determine (primary) group id
593    groupid=''
594    if [ ".$opt_e" = .yes ] && [ ".`echo $text | grep '%[gG]'`" != . ]; then
595        groupid="`(id -g ${username}) 2>/dev/null`"
596        if [ ".$groupid" = . ]; then
597            str="`(id) 2>/dev/null`"
598            if [ ".`echo $str | grep 'gid[ 	]*=[ 	]*[0-9]*('`" != . ]; then
599                groupid=`echo $str | sed -e 's/^.*gid[ 	]*=[ 	]*//' -e 's/(.*$//'`
600            fi
601            if [ ".$groupid" = . ]; then
602                groupid=`(getent passwd ${username}) 2>/dev/null | \
603                         sed -e 's/[^:]*:[^:]*:[^:]*://' -e 's/:.*$//'`
604                if [ ".$groupid" = . ]; then
605                    groupid=`grep "^${username}:" /etc/passwd 2>/dev/null | \
606                             sed -e 's/[^:]*:[^:]*:[^:]*://' -e 's/:.*$//'`
607                    if [ ".$groupid" = . ]; then
608                        groupid=`(ypcat passwd) 2>/dev/null | grep "^${username}:" | \
609                                 sed -e 's/[^:]*:[^:]*:[^:]*://' -e 's/:.*$//'`
610                        if [ ".$groupid" = . ]; then
611                            groupid='?'
612                        fi
613                    fi
614                fi
615            fi
616        fi
617    fi
618
619    #   determine (primary) group name
620    groupname=''
621    if [ ".$opt_e" = .yes ] && [ ".`echo $text | grep '%g'`" != . ]; then
622        groupname="`(id -gn ${username}) 2>/dev/null`"
623        if [ ".$groupname" = . ]; then
624            str="`(id) 2>/dev/null`"
625            if [ ".`echo $str | grep 'gid[ 	]*=[ 	]*[0-9]*('`" != . ]; then
626                groupname=`echo $str | sed -e 's/^.*gid[ 	]*=[ 	]*[0-9]*(//' -e 's/).*$//'`
627            fi
628            if [ ".$groupname" = . ]; then
629                groupname=`(getent group) 2>/dev/null | \
630                           grep "^[^:]*:[^:]*:${groupid}:" | \
631                           sed -e 's/:.*$//'`
632                if [ ".$groupname" = . ]; then
633                    groupname=`grep "^[^:]*:[^:]*:${groupid}:" /etc/group 2>/dev/null | \
634                               sed -e 's/:.*$//'`
635                    if [ ".$groupname" = . ]; then
636                        groupname=`(ypcat group) 2>/dev/null | \
637                                   grep "^[^:]*:[^:]*:${groupid}:" | \
638                                   sed -e 's/:.*$//'`
639                        if [ ".$groupname" = . ]; then
640                            groupname='?'
641                        fi
642                    fi
643                fi
644            fi
645        fi
646    fi
647
648    #   determine host and domain name
649    hostname=''
650    domainname=''
651    if [ ".$opt_e" = .yes ] && [ ".`echo $text | grep '%h'`" != . ]; then
652        hostname="`(uname -n) 2>/dev/null |\
653                   awk '{ printf("%s", $1); }'`"
654        if [ ".$hostname" = . ]; then
655            hostname="`(hostname) 2>/dev/null |\
656                       awk '{ printf("%s", $1); }'`"
657            if [ ".$hostname" = . ]; then
658                hostname='unknown'
659            fi
660        fi
661        case $hostname in
662            *.* )
663                domainname=".`echo $hostname | cut -d. -f2-`"
664                hostname="`echo $hostname | cut -d. -f1`"
665                ;;
666        esac
667    fi
668    if [ ".$opt_e" = .yes ] && [ ".`echo $text | grep '%d'`" != . ]; then
669        if [ ".$domainname" = . ]; then
670            if [ -f /etc/resolv.conf ]; then
671                domainname="`grep '^[ 	]*domain' /etc/resolv.conf | sed -e 'q' |\
672                             sed -e 's/.*domain//' \
673                                 -e 's/^[ 	]*//' -e 's/^ *//' -e 's/^	*//' \
674                                 -e 's/^\.//' -e 's/^/./' |\
675                             awk '{ printf("%s", $1); }'`"
676                if [ ".$domainname" = . ]; then
677                    domainname="`grep '^[ 	]*search' /etc/resolv.conf | sed -e 'q' |\
678                                 sed -e 's/.*search//' \
679                                     -e 's/^[ 	]*//' -e 's/^ *//' -e 's/^	*//' \
680                                     -e 's/ .*//' -e 's/	.*//' \
681                                     -e 's/^\.//' -e 's/^/./' |\
682                                 awk '{ printf("%s", $1); }'`"
683                fi
684            fi
685        fi
686    fi
687
688    #   determine current time
689    time_day=''
690    time_month=''
691    time_year=''
692    time_monthname=''
693    if [ ".$opt_e" = .yes ] && [ ".`echo $text | grep '%[DMYm]'`" != . ]; then
694        time_day=`date '+%d'`
695        time_month=`date '+%m'`
696        time_year=`date '+%Y' 2>/dev/null`
697        if [ ".$time_year" = . ]; then
698            time_year=`date '+%y'`
699            case $time_year in
700                [5-9][0-9]) time_year="19$time_year" ;;
701                [0-4][0-9]) time_year="20$time_year" ;;
702            esac
703        fi
704        case $time_month in
705            1|01) time_monthname='Jan' ;;
706            2|02) time_monthname='Feb' ;;
707            3|03) time_monthname='Mar' ;;
708            4|04) time_monthname='Apr' ;;
709            5|05) time_monthname='May' ;;
710            6|06) time_monthname='Jun' ;;
711            7|07) time_monthname='Jul' ;;
712            8|08) time_monthname='Aug' ;;
713            9|09) time_monthname='Sep' ;;
714              10) time_monthname='Oct' ;;
715              11) time_monthname='Nov' ;;
716              12) time_monthname='Dec' ;;
717        esac
718    fi
719
720    #   expand special ``%x'' constructs
721    if [ ".$opt_e" = .yes ]; then
722        text=`echo $seo "$text" |\
723              sed -e "s/%B/${term_bold}/g" \
724                  -e "s/%b/${term_norm}/g" \
725                  -e "s/%u/${username}/g" \
726                  -e "s/%U/${userid}/g" \
727                  -e "s/%g/${groupname}/g" \
728                  -e "s/%G/${groupid}/g" \
729                  -e "s/%h/${hostname}/g" \
730                  -e "s/%d/${domainname}/g" \
731                  -e "s/%D/${time_day}/g" \
732                  -e "s/%M/${time_month}/g" \
733                  -e "s/%Y/${time_year}/g" \
734                  -e "s/%m/${time_monthname}/g" 2>/dev/null`
735    fi
736
737    #   create output
738    if [ .$opt_n = .no ]; then
739        echo $seo "$text"
740    else
741        #   the harder part: echo -n is best, because
742        #   awk may complain about some \xx sequences.
743        if [ ".$minusn" != . ]; then
744            echo $seo $minusn "$text"
745        else
746            echo dummy | awk '{ printf("%s", TEXT); }' TEXT="$text"
747        fi
748    fi
749
750    shtool_exit 0
751    ;;
752
753install )
754    ##
755    ##  install -- Install a program, script or datafile
756    ##  Copyright (c) 1997-2005 Ralf S. Engelschall <rse@engelschall.com>
757    ##
758
759    #   special case: "shtool install -d <dir> [...]" internally
760    #   maps to "shtool mkdir -f -p -m 755 <dir> [...]"
761    if [ "$opt_d" = yes ]; then
762        cmd="$0 mkdir -f -p -m 755"
763        if [ ".$opt_o" != . ]; then
764            cmd="$cmd -o '$opt_o'"
765        fi
766        if [ ".$opt_g" != . ]; then
767            cmd="$cmd -g '$opt_g'"
768        fi
769        if [ ".$opt_v" = .yes ]; then
770            cmd="$cmd -v"
771        fi
772        if [ ".$opt_t" = .yes ]; then
773            cmd="$cmd -t"
774        fi
775        for dir in "$@"; do
776            eval "$cmd $dir" || shtool_exit $?
777        done
778        shtool_exit 0
779    fi
780
781    #   determine source(s) and destination
782    argc=$#
783    srcs=""
784    while [ $# -gt 1 ]; do
785        srcs="$srcs $1"
786        shift
787    done
788    dstpath="$1"
789
790    #   type check for destination
791    dstisdir=0
792    if [ -d $dstpath ]; then
793        dstpath=`echo "$dstpath" | sed -e 's:/$::'`
794        dstisdir=1
795    fi
796
797    #   consistency check for destination
798    if [ $argc -gt 2 ] && [ $dstisdir = 0 ]; then
799        echo "$msgprefix:Error: multiple sources require destination to be directory" 1>&2
800        shtool_exit 1
801    fi
802
803    #   iterate over all source(s)
804    for src in $srcs; do
805        dst=$dstpath
806
807        #   if destination is a directory, append the input filename
808        if [ $dstisdir = 1 ]; then
809            dstfile=`echo "$src" | sed -e 's;.*/\([^/]*\)$;\1;'`
810            dst="$dst/$dstfile"
811        fi
812
813        #   check for correct arguments
814        if [ ".$src" = ".$dst" ]; then
815            echo "$msgprefix:Warning: source and destination are the same - skipped" 1>&2
816            continue
817        fi
818        if [ -d "$src" ]; then
819            echo "$msgprefix:Warning: source \`$src' is a directory - skipped" 1>&2
820            continue
821        fi
822
823        #   make a temp file name in the destination directory
824        dsttmp=`echo $dst |\
825                sed -e 's;[^/]*$;;' -e 's;\(.\)/$;\1;' -e 's;^$;.;' \
826                    -e "s;\$;/#INST@$$#;"`
827
828        #   verbosity
829        if [ ".$opt_v" = .yes ]; then
830            echo "$src -> $dst" 1>&2
831        fi
832
833        #   copy or move the file name to the temp name
834        #   (because we might be not allowed to change the source)
835        if [ ".$opt_C" = .yes ]; then
836            opt_c=yes
837        fi
838        if [ ".$opt_c" = .yes ]; then
839            if [ ".$opt_t" = .yes ]; then
840                echo "cp $src $dsttmp" 1>&2
841            fi
842            cp $src $dsttmp || shtool_exit $?
843        else
844            if [ ".$opt_t" = .yes ]; then
845                echo "mv $src $dsttmp" 1>&2
846            fi
847            mv $src $dsttmp || shtool_exit $?
848        fi
849
850        #   adjust the target file
851        if [ ".$opt_e" != . ]; then
852            sed='sed'
853            OIFS="$IFS"; IFS="$ASC_NL"; set -- $opt_e; IFS="$OIFS"
854            for e
855            do
856                sed="$sed -e '$e'"
857            done
858            cp $dsttmp $dsttmp.old
859            chmod u+w $dsttmp
860            eval "$sed <$dsttmp.old >$dsttmp" || shtool_exit $?
861            rm -f $dsttmp.old
862        fi
863        if [ ".$opt_s" = .yes ]; then
864            if [ ".$opt_t" = .yes ]; then
865                echo "strip $dsttmp" 1>&2
866            fi
867            strip $dsttmp || shtool_exit $?
868        fi
869        if [ ".$opt_o" != . ]; then
870            if [ ".$opt_t" = .yes ]; then
871                echo "chown $opt_o $dsttmp" 1>&2
872            fi
873            chown $opt_o $dsttmp || shtool_exit $?
874        fi
875        if [ ".$opt_g" != . ]; then
876            if [ ".$opt_t" = .yes ]; then
877                echo "chgrp $opt_g $dsttmp" 1>&2
878            fi
879            chgrp $opt_g $dsttmp || shtool_exit $?
880        fi
881        if [ ".$opt_m" != ".-" ]; then
882            if [ ".$opt_t" = .yes ]; then
883                echo "chmod $opt_m $dsttmp" 1>&2
884            fi
885            chmod $opt_m $dsttmp || shtool_exit $?
886        fi
887
888        #   determine whether to do a quick install
889        #   (has to be done _after_ the strip was already done)
890        quick=no
891        if [ ".$opt_C" = .yes ]; then
892            if [ -r $dst ]; then
893                if cmp -s $src $dst; then
894                    quick=yes
895                fi
896            fi
897        fi
898
899        #   finally, install the file to the real destination
900        if [ $quick = yes ]; then
901            if [ ".$opt_t" = .yes ]; then
902                echo "rm -f $dsttmp" 1>&2
903            fi
904            rm -f $dsttmp
905        else
906            if [ ".$opt_t" = .yes ]; then
907                echo "rm -f $dst && mv $dsttmp $dst" 1>&2
908            fi
909            rm -f $dst && mv $dsttmp $dst
910        fi
911    done
912
913    shtool_exit 0
914    ;;
915
916mkdir )
917    ##
918    ##  mkdir -- Make one or more directories
919    ##  Copyright (c) 1996-2005 Ralf S. Engelschall <rse@engelschall.com>
920    ##
921
922    errstatus=0
923    for p in ${1+"$@"}; do
924        #   if the directory already exists...
925        if [ -d "$p" ]; then
926            if [ ".$opt_f" = .no ] && [ ".$opt_p" = .no ]; then
927                echo "$msgprefix:Error: directory already exists: $p" 1>&2
928                errstatus=1
929                break
930            else
931                continue
932            fi
933        fi
934        #   if the directory has to be created...
935        if [ ".$opt_p" = .no ]; then
936            if [ ".$opt_t" = .yes ]; then
937                echo "mkdir $p" 1>&2
938            fi
939            mkdir $p || errstatus=$?
940            if [ ".$opt_o" != . ]; then
941                if [ ".$opt_t" = .yes ]; then
942                    echo "chown $opt_o $p" 1>&2
943                fi
944                chown $opt_o $p || errstatus=$?
945            fi
946            if [ ".$opt_g" != . ]; then
947                if [ ".$opt_t" = .yes ]; then
948                    echo "chgrp $opt_g $p" 1>&2
949                fi
950                chgrp $opt_g $p || errstatus=$?
951            fi
952            if [ ".$opt_m" != . ]; then
953                if [ ".$opt_t" = .yes ]; then
954                    echo "chmod $opt_m $p" 1>&2
955                fi
956                chmod $opt_m $p || errstatus=$?
957            fi
958        else
959            #   the smart situation
960            set fnord `echo ":$p" |\
961                       sed -e 's/^:\//%/' \
962                           -e 's/^://' \
963                           -e 's/\// /g' \
964                           -e 's/^%/\//'`
965            shift
966            pathcomp=''
967            for d in ${1+"$@"}; do
968                pathcomp="$pathcomp$d"
969                case "$pathcomp" in
970                    -* ) pathcomp="./$pathcomp" ;;
971                esac
972                if [ ! -d "$pathcomp" ]; then
973                    if [ ".$opt_t" = .yes ]; then
974                        echo "mkdir $pathcomp" 1>&2
975                    fi
976                    mkdir $pathcomp || errstatus=$?
977                    if [ ".$opt_o" != . ]; then
978                        if [ ".$opt_t" = .yes ]; then
979                            echo "chown $opt_o $pathcomp" 1>&2
980                        fi
981                        chown $opt_o $pathcomp || errstatus=$?
982                    fi
983                    if [ ".$opt_g" != . ]; then
984                        if [ ".$opt_t" = .yes ]; then
985                            echo "chgrp $opt_g $pathcomp" 1>&2
986                        fi
987                        chgrp $opt_g $pathcomp || errstatus=$?
988                    fi
989                    if [ ".$opt_m" != . ]; then
990                        if [ ".$opt_t" = .yes ]; then
991                            echo "chmod $opt_m $pathcomp" 1>&2
992                        fi
993                        chmod $opt_m $pathcomp || errstatus=$?
994                    fi
995                fi
996                pathcomp="$pathcomp/"
997            done
998        fi
999    done
1000
1001    shtool_exit $errstatus
1002    ;;
1003
1004fixperm )
1005    ##
1006    ##  fixperm -- Fix file permissions inside a source tree
1007    ##  Copyright (c) 1996-2005 Ralf S. Engelschall <rse@engelschall.com>
1008    ##
1009
1010    paths="$*"
1011
1012    #   check whether the test command supports the -x option
1013    if [ -x /bin/sh ] 2>/dev/null; then
1014        minusx="-x"
1015    else
1016        minusx="-r"
1017    fi
1018
1019    #   iterate over paths
1020    for p in $paths; do
1021        for file in `find $p -depth -print`; do
1022            if [ -f $file ]; then
1023                if [ $minusx $file ]; then
1024                    if [ ".$opt_v" = .yes ]; then
1025                        echo "-rwxr-xr-x $file" 2>&1
1026                    fi
1027                    if [ ".$opt_t" = .yes ]; then
1028                        echo "chmod 755 $file" 2>&1
1029                    fi
1030                    chmod 755 $file
1031                else
1032                    if [ ".$opt_v" = .yes ]; then
1033                        echo "-rw-r--r-- $file" 2>&1
1034                    fi
1035                    if [ ".$opt_t" = .yes ]; then
1036                        echo "chmod 644 $file" 2>&1
1037                    fi
1038                    chmod 644 $file
1039                fi
1040                continue
1041            fi
1042            if [ -d $file ]; then
1043                if [ ".$opt_v" = .yes ]; then
1044                    echo "drwxr-xr-x $file" 2>&1
1045                fi
1046                if [ ".$opt_t" = .yes ]; then
1047                    echo "chmod 755 $file" 2>&1
1048                fi
1049                chmod 755 $file
1050                continue
1051            fi
1052            if [ ".$opt_v" = .yes ]; then
1053                echo "?????????? $file" 2>&1
1054            fi
1055        done
1056    done
1057
1058    shtool_exit 0
1059    ;;
1060
1061tarball )
1062    ##
1063    ##  tarball -- Roll distribution tarballs
1064    ##  Copyright (c) 1999-2005 Ralf S. Engelschall <rse@engelschall.com>
1065    ##
1066
1067    srcs="$*"
1068
1069    #   check whether the test command supports the -x option
1070    if [ -x /bin/sh ] 2>/dev/null; then
1071        minusx="-x"
1072    else
1073        minusx="-r"
1074    fi
1075
1076    #   find the tools
1077    paths="`echo $PATH |\
1078            sed -e 's%/*:%:%g' -e 's%/*$%%' \
1079                -e 's/^:/.:/' -e 's/::/:.:/g' -e 's/:$/:./' \
1080                -e 's/:/ /g'`"
1081    for spec in find:gfind,find tar:gtar,tar tardy:tardy,tarcust; do
1082        prg=`echo $spec | sed -e 's/:.*$//'`
1083        tools=`echo $spec | sed -e 's/^.*://'`
1084        eval "prg_${prg}=''"
1085        #   iterate over tools
1086        for tool in `echo $tools | sed -e 's/,/ /g'`; do
1087            #   iterate over paths
1088            for path in $paths; do
1089                if [ $minusx "$path/$tool" ] && [ ! -d "$path/$tool" ]; then
1090                    eval "prg_${prg}=\"$path/$tool\""
1091                    break
1092                fi
1093            done
1094            eval "val=\$prg_${prg}"
1095            if [ ".$val" != . ]; then
1096                break
1097            fi
1098        done
1099    done
1100
1101    #   expand source paths
1102    exclude=''
1103    for pat in `echo $opt_e | sed 's/,/ /g'`; do
1104        exclude="$exclude | grep -v '$pat'"
1105    done
1106    if [ ".$opt_t" = .yes ]; then
1107        echo "cp /dev/null $tmpfile.lst" 1>&2
1108    fi
1109    cp /dev/null $tmpfile.lst
1110    for src in $srcs; do
1111        if [ -d $src ]; then
1112            if [ ".$opt_t" = .yes ]; then
1113                echo "(cd $src && $prg_find . -type f -depth -print) | sed -e 's:^\\.\$::' -e 's:^\\./::' | cat $exclude >>$tmpfile.lst" 1>&2
1114            fi
1115            (cd $src && $prg_find . -type f -depth -print) |\
1116            sed -e 's:^\.$::' -e 's:^\./::' | eval cat $exclude >>$tmpfile.lst
1117        else
1118            if [ ".$opt_t" = .yes ]; then
1119                echo "echo $src >>$tmpfile.lst" 1>&2
1120            fi
1121            echo $src >>$tmpfile.lst
1122        fi
1123    done
1124    sort <$tmpfile.lst >$tmpfile.lst.n
1125    mv $tmpfile.lst.n $tmpfile.lst
1126    if [ ".$opt_v" = .yes ]; then
1127        cat $tmpfile.lst | sed -e 's/^/  /' 1>&2
1128    fi
1129
1130    #   determine tarball file and directory name
1131    if [ ".$opt_o" != . ]; then
1132        tarfile="$opt_o"
1133        if [ ".$opt_d" != . ]; then
1134            tarname="$opt_d"
1135        else
1136            tarname=`echo $tarfile | sed -e 's/\.tar.*$//' -e 's;.*/\([^/]*\)$;\1;'`
1137        fi
1138    else
1139        if [ ".$opt_d" != . ]; then
1140            tarname="$opt_d"
1141        elif [ -d "$from" ]; then
1142            tarname=`echo $from | sed -e 's;.*/\([^/]*\)$;\1;'`
1143        else
1144            tarname="out"
1145        fi
1146        tarfile="$tarname.tar"
1147    fi
1148
1149    #   roll the tarball
1150    compress=''
1151    if [ ".$opt_c" != . ]; then
1152        compress="| $opt_c"
1153    fi
1154    if [ ".$prg_tardy" != . ]; then
1155        #   the elegant hackers way
1156        tardy_opt="--prefix=$tarname"
1157        tardy_opt="$tardy_opt --user_number=0 --group_number=0" # security!
1158        if [ ".$opt_u" != . ]; then
1159            tardy_opt="$tardy_opt --user_name=$opt_u"
1160        fi
1161        if [ ".$opt_g" != . ]; then
1162            tardy_opt="$tardy_opt --group_name=$opt_g"
1163        fi
1164        if [ ".$opt_t" = .yes ]; then
1165            echo "cat $tmpfile.lst | xargs $prg_tar cf - | $prg_tardy $tardy_opt | cat $compress >$tmpfile.out" 1>&2
1166        fi
1167        cat $tmpfile.lst |\
1168        xargs $prg_tar cf - |\
1169        $prg_tardy $tardy_opt |\
1170        eval cat $compress >$tmpfile.out
1171        if [ ".$opt_t" = .yes ]; then
1172            echo "cp $tmpfile.out $tarfile" 1>&2
1173        fi
1174        cp $tmpfile.out $tarfile
1175    else
1176        #  the portable standard way
1177        if [ ".$opt_t" = .yes ]; then
1178            echo "mkdir $tmpdir/$tarname" 1>&2
1179        fi
1180        mkdir $tmpdir/$tarname || shtool_exit 1
1181        if [ ".$opt_t" = .yes ]; then
1182            echo "cat $tmpfile.lst | xargs $prg_tar cf - | (cd $tmpdir/$tarname && $prg_tar xf -)" 1>&2
1183        fi
1184        cat $tmpfile.lst |\
1185        xargs $prg_tar cf - |\
1186        (cd $tmpdir/$tarname && $prg_tar xf -)
1187        if [ ".$opt_u" != . ]; then
1188            if [ ".$opt_t" = .yes ]; then
1189                echo "chown -R $opt_u $tmpdir/$tarname >/dev/null 2>&1" 2>&1
1190            fi
1191            chown -R $opt_u $tmpdir/$tarname >/dev/null 2>&1 ||\
1192            echo "$msgprefix:Warning: cannot set user name \`$opt_u' (would require root privileges)"
1193        fi
1194        if [ ".$opt_g" != . ]; then
1195            if [ ".$opt_t" = .yes ]; then
1196                echo "chgrp -R $opt_g $tmpdir/$tarname >/dev/null 2>&1" 2>&1
1197            fi
1198            chgrp -R $opt_g $tmpdir/$tarname >/dev/null 2>&1 ||\
1199            echo "$msgprefix:Warning: cannot set group name \`$opt_g' (would require root privileges)"
1200        fi
1201        if [ ".$opt_t" = .yes ]; then
1202            echo "(cd $tmpdir && $prg_find $tarname -type f -depth -print | sort | xargs $prg_tar cf -) | cat $compress >$tmpfile.out" 1>&2
1203        fi
1204        (cd $tmpdir && $prg_find $tarname -type f -depth -print | sort | xargs $prg_tar cf -) |\
1205        eval cat $compress >$tmpfile.out
1206        if [ ".$opt_t" = .yes ]; then
1207            echo "cp $tmpfile.out $tarfile" 1>&2
1208        fi
1209        cp $tmpfile.out $tarfile
1210        if [ ".$opt_t" = .yes ]; then
1211            echo "rm -rf $tmpdir/$tarname" 1>&2
1212        fi
1213        rm -rf $tmpdir/$tarname
1214    fi
1215
1216    #   cleanup
1217    if [ ".$opt_t" = .yes ]; then
1218        echo "rm -f $tmpfile.lst $tmpfile.out" 1>&2
1219    fi
1220    rm -f $tmpfile.lst $tmpfile.out
1221
1222    shtool_exit 0
1223    ;;
1224
1225version )
1226    ##
1227    ##  version -- Maintain a version information file
1228    ##  Copyright (c) 1994-2005 Ralf S. Engelschall <rse@engelschall.com>
1229    ##
1230
1231    file="$1"
1232
1233    #   determine prefix and name
1234    name="$opt_n"
1235    prefix="$opt_p"
1236
1237    #   determine current version
1238    triple="$opt_s"
1239    if [ ".$triple" != . ]; then
1240        #   use given triple
1241        if [ ".`echo $triple | grep '[0-9]*.[0-9]*[sabp.][0-9]*'`" = . ]; then
1242            echo "$msgprefix:Error: invalid argument to option \`-s': \`$opt_s'" 1>&2
1243            shtool_exit 1
1244        fi
1245        eval `echo $triple |\
1246              sed -e 's%\([0-9]*\)\.\([0-9]*\)\([sabp.]\)\([0-9]*\).*%\
1247              ver="\1";rev="\2";typ="\3";lev="\4"%'`
1248        tim=calc
1249    elif [ -r $file ]; then
1250        #   determine triple from given file
1251        eval `grep 'Version [0-9]*.[0-9]*[sabp.][0-9]* ([0-9]*-[a-zA-Z]*-[0-9]*)' $file |\
1252              sed -e 's%.*Version \([0-9]*\)\.\([0-9]*\)\([sabp.]\)\([0-9]*\) (\([0-9]*-[a-zA-Z]*-[0-9]*\)).*%\
1253              ver="\1";rev="\2";typ="\3";lev="\4";tim="\5"%' -e 'q'`
1254    else
1255        #   intialise to first version
1256        ver=0
1257        rev=1
1258        typ=.
1259        lev=0
1260        tim=calc
1261    fi
1262
1263    #   determine new version in batch
1264    if [ ".$opt_i" != . ]; then
1265        case $opt_i in
1266            v ) ver=`expr $ver + 1`
1267                rev=0
1268                lev=0
1269                ;;
1270            r ) rev=`expr $rev + 1`
1271                lev=0
1272                ;;
1273            l ) lev=`expr $lev + 1`
1274                ;;
1275            * ) echo "$msgprefix:Error: invalid argument to option \`-i': \`$opt_i'" 1>&2
1276                shtool_exit 1
1277                ;;
1278        esac
1279        tim=calc
1280    fi
1281
1282    #   determine new version interactively
1283    if [ ".$opt_e" = .yes ]; then
1284        echo "old version: ${ver}.${rev}${typ}${lev}"
1285        while [ 1 ]; do
1286            echo dummy | awk '{ printf("new version: "); }'
1287            read triple
1288            case $triple in
1289                [0-9]*.[0-9]*[sabp.][0-9]* )
1290                    ;;
1291                * ) echo "$msgprefix:Error: invalid version string entered: \`$triple'" 1>&2
1292                    continue
1293                    ;;
1294            esac
1295            break
1296        done
1297        eval `echo $triple |\
1298              sed -e 's%^\([0-9]*\)\.\([0-9]*\)\([sabp.]\)\([0-9]*\)$%\
1299              ver="\1";rev="\2";typ="\3";lev="\4"%'`
1300        tim=calc
1301    fi
1302
1303    #   determine hexadecimal and libtool value of version
1304    case $typ in
1305        a     ) typnum=0;  levnum=$lev ;;
1306        b     ) typnum=1;  levnum=$lev ;;
1307        p | . ) typnum=2;  levnum=$lev ;;
1308        s     ) typnum=15; levnum=255  ;; # snapshots are special
1309    esac
1310    hex=`echo "$ver:$rev:$typnum:$levnum" |\
1311         awk -F: '{ printf("0x%x%02x%1x%02x", $1, $2, $3, $4); }' |\
1312         tr 'abcdef' 'ABCDEF'`
1313    ltv=`echo "$ver:$rev:$typnum:$levnum" |\
1314         awk -F: '{ printf("%d:%d", $1*10 + $2, $3*10 + $4); }'`
1315
1316    #   determine date
1317    if [ ".$tim" = .calc ]; then
1318        day=`date '+%d'`
1319        month=`date '+%m'`
1320        year=`date '+%Y' 2>/dev/null`
1321        if [ ".$time_year" = . ]; then
1322            year=`date '+%y'`
1323            case $year in
1324                [5-9][0-9]) year="19$year" ;;
1325                [0-4][0-9]) year="20$year" ;;
1326            esac
1327        fi
1328        case $month in
1329            1|01) month='Jan' ;;
1330            2|02) month='Feb' ;;
1331            3|03) month='Mar' ;;
1332            4|04) month='Apr' ;;
1333            5|05) month='May' ;;
1334            6|06) month='Jun' ;;
1335            7|07) month='Jul' ;;
1336            8|08) month='Aug' ;;
1337            9|09) month='Sep' ;;
1338              10) month='Oct' ;;
1339              11) month='Nov' ;;
1340              12) month='Dec' ;;
1341        esac
1342        tim="${day}-${month}-${year}"
1343    fi
1344
1345    #   perform result actions
1346    mode=show
1347    if [ ".$opt_i" != . ]; then
1348        mode=edit
1349    elif [ ".$opt_e" = .yes ]; then
1350        mode=edit
1351    elif [ ".$opt_s" != . ]; then
1352        mode=edit
1353    fi
1354    if [ ".$mode" = .show ]; then
1355        #   just display the current version
1356        case $opt_d in
1357            short )
1358                echo "${ver}.${rev}${typ}${lev}"
1359                ;;
1360            long )
1361                echo "${ver}.${rev}${typ}${lev} ($tim)"
1362                ;;
1363            libtool )
1364                echo "${ltv}"
1365                ;;
1366            hex )
1367                echo "${hex}"
1368                ;;
1369            * ) echo "$msgprefix:Error: invalid argument to option \`-d': \`$opt_d'" 1>&2
1370                shtool_exit 1
1371                ;;
1372        esac
1373    else
1374        #   update the version file
1375
1376        #   pre-generate various strings
1377        triple="${ver}.${rev}${typ}${lev}"
1378        vHex="$hex"
1379        vShort="${triple}"
1380        vLong="${triple} (${tim})"
1381        vTeX="This is ${name}, Version ${triple} (${tim})"
1382        vGNU="${name} ${triple} (${tim})"
1383        vWeb="${name}/${triple}"
1384        vSCCS="@(#)${name} ${triple} (${tim})"
1385        vRCS="\$Id: ${name} ${triple} (${tim}) \$"
1386
1387        #   determine string out of filename
1388        #   (do NOT try to optimize this in any way because of portability)
1389        filestr=`echo $file |\
1390                 tr 'abcdefghijklmnopqrstuvwxyz./%+' \
1391                    'ABCDEFGHIJKLMNOPQRSTUVWXYZ____' | sed -e 's/-/_/g'`
1392
1393        #   generate uppercase prefix
1394        prefixupper=`echo $prefix |\
1395                     tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
1396
1397        #   create the version file according the the selected language
1398        echo "new version: ${vLong}"
1399
1400        cp /dev/null $file
1401        case $opt_l in
1402            txt )
1403                echo >>$file ""
1404                echo >>$file "  ${file} -- Version Information for ${name} (syntax: Text)"
1405                echo >>$file "  [automatically generated and maintained by GNU shtool]"
1406                echo >>$file ""
1407                echo >>$file "  $vTeX"
1408                echo >>$file ""
1409                ;;
1410            c )
1411                echo >>$file "/*"
1412                echo >>$file "**  ${file} -- Version Information for ${name} (syntax: C/C++)"
1413                echo >>$file "**  [automatically generated and maintained by GNU shtool]"
1414                echo >>$file "*/"
1415                echo >>$file ""
1416                echo >>$file "#ifdef _${filestr}_AS_HEADER_"
1417                echo >>$file ""
1418                echo >>$file "#ifndef _${filestr}_"
1419                echo >>$file "#define _${filestr}_"
1420                echo >>$file ""
1421                echo >>$file "#define ${prefixupper}VERSION ${vHex}"
1422                echo >>$file ""
1423                echo >>$file "typedef struct {"
1424                echo >>$file "    const int   v_hex;"
1425                echo >>$file "    const char *v_short;"
1426                echo >>$file "    const char *v_long;"
1427                echo >>$file "    const char *v_tex;"
1428                echo >>$file "    const char *v_gnu;"
1429                echo >>$file "    const char *v_web;"
1430                echo >>$file "    const char *v_sccs;"
1431                echo >>$file "    const char *v_rcs;"
1432                echo >>$file "} ${prefix}version_t;"
1433                echo >>$file ""
1434                echo >>$file "extern ${prefix}version_t ${prefix}version;"
1435                echo >>$file ""
1436                echo >>$file "#endif /* _${filestr}_ */"
1437                echo >>$file ""
1438                echo >>$file "#else /* _${filestr}_AS_HEADER_ */"
1439                echo >>$file ""
1440                echo >>$file "#define _${filestr}_AS_HEADER_"
1441                echo >>$file "#include \"${file}\""
1442                echo >>$file "#undef  _${filestr}_AS_HEADER_"
1443                echo >>$file ""
1444                echo >>$file "${prefix}version_t ${prefix}version = {"
1445                echo >>$file "    ${vHex},"
1446                echo >>$file "    \"${vShort}\","
1447                echo >>$file "    \"${vLong}\","
1448                echo >>$file "    \"${vTeX}\","
1449                echo >>$file "    \"${vGNU}\","
1450                echo >>$file "    \"${vWeb}\","
1451                echo >>$file "    \"${vSCCS}\","
1452                echo >>$file "    \"${vRCS}\""
1453                echo >>$file "};"
1454                echo >>$file ""
1455                echo >>$file "#endif /* _${filestr}_AS_HEADER_ */"
1456                echo >>$file ""
1457                ;;
1458            m4 )
1459                echo >>$file "##"
1460                echo >>$file "##  ${file} -- Version Information for ${name} (syntax: M4)"
1461                echo >>$file "##  [automatically generated and maintained by GNU shtool]"
1462                echo >>$file "##"
1463                echo >>$file ""
1464                echo >>$file "m4_define([v_hex],   [${vHex}])"
1465                echo >>$file "m4_define([v_short], [${vShort}])"
1466                echo >>$file "m4_define([v_long],  [${vLong}])"
1467                echo >>$file "m4_define([v_tex],   [${vTeX}])"
1468                echo >>$file "m4_define([v_gnu],   [${vGNU}])"
1469                echo >>$file "m4_define([v_web],   [${vWeb}])"
1470                echo >>$file "m4_define([v_sccs],  [${vSCCS}])"
1471                echo >>$file "m4_define([v_rcs],   [${vRCS}])"
1472                echo >>$file ""
1473                ;;
1474            perl )
1475                echo >>$file "##"
1476                echo >>$file "##  ${file} -- Version Information for ${name} (syntax: Perl)"
1477                echo >>$file "##  [automatically generated and maintained by GNU shtool]"
1478                echo >>$file "##"
1479                echo >>$file ""
1480                echo >>$file "our \$${prefix}version = {"
1481                echo >>$file "    'v_hex'   => ${vHex},"
1482                echo >>$file "    'v_short' => \"${vShort}\","
1483                echo >>$file "    'v_long'  => \"${vLong}\","
1484                echo >>$file "    'v_tex'   => \"${vTeX}\","
1485                echo >>$file "    'v_gnu'   => \"${vGNU}\","
1486                echo >>$file "    'v_web'   => \"${vWeb}\","
1487                echo >>$file "    'v_sccs'  => \"${vSCCS}\","
1488                echo >>$file "    'v_rcs'   => \"\\${vRCS}/\""
1489                echo >>$file "};"
1490                echo >>$file ""
1491                echo >>$file "1;"
1492                echo >>$file ""
1493                ;;
1494            python )
1495                echo >>$file "##"
1496                echo >>$file "##  ${file} -- Version Information for ${name} (syntax: Python)"
1497                echo >>$file "##  [automatically generated and maintained by GNU shtool]"
1498                echo >>$file "##"
1499                echo >>$file ""
1500                echo >>$file "class ${prefix}version:"
1501                echo >>$file "    v_hex       = ${vHex}"
1502                echo >>$file "    v_short     = \"${vShort}\""
1503                echo >>$file "    v_long      = \"${vLong}\""
1504                echo >>$file "    v_tex       = \"${vTeX}\""
1505                echo >>$file "    v_gnu       = \"${vGNU}\""
1506                echo >>$file "    v_web       = \"${vWeb}\""
1507                echo >>$file "    v_sccs      = \"${vSCCS}\""
1508                echo >>$file "    v_rcs       = \"${vRCS}\""
1509                echo >>$file ""
1510                ;;
1511            * ) echo "$msgprefix:Error: invalid argument to option \`-l': \`$opt_l'" 1>&2
1512                shtool_exit 1
1513                ;;
1514        esac
1515    fi
1516
1517    shtool_exit 0
1518    ;;
1519
1520esac
1521
1522shtool_exit 0
1523
1524