1#!/bin/sh
2##
3##  GNU shtool -- The GNU Portable Shell Tool
4##  Copyright (c) 1994-2006 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.6 (19-Apr-2006)
10##  Contents: all 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##    mdate      Pretty-print modification time of a file or dir
43##    table      Pretty-print a field-separated list as a table
44##    prop       Display progress with a running propeller
45##    move       Move files with simultaneous substitution
46##    install    Install a program, script or datafile
47##    mkdir      Make one or more directories
48##    mkln       Make link with calculation of relative paths
49##    mkshadow   Make a shadow tree through symbolic links
50##    fixperm    Fix file permissions inside a source tree
51##    rotate     Logfile rotation
52##    tarball    Roll distribution tarballs
53##    subst      Apply sed(1) substitution operations
54##    platform   Platform Identification Utility
55##    arx        Extended archive command
56##    slo        Separate linker options by library class
57##    scpp       Sharing C Pre-Processor
58##    version    Maintain a version information file
59##    path       Deal with program paths
60##
61
62#   maximum Bourne-Shell compatibility
63if [ ".$ZSH_VERSION" != . ] && (emulate sh) >/dev/null 2>&1; then
64    #   reconfigure zsh(1)
65    emulate sh
66    NULLCMD=:
67    alias -g '${1+"$@"}'='"$@"'
68elif [ ".$BASH_VERSION" != . ] && (set -o posix) >/dev/null 2>&1; then
69    #   reconfigure bash(1)
70    set -o posix
71fi
72
73#   maximum independence of NLS nuisances
74for var in \
75    LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
76    LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
77    LC_TELEPHONE LC_TIME
78do
79    if (set +x; test -z "`(eval $var=C; export $var) 2>&1`"); then
80        eval $var=C; export $var
81    else
82        unset $var
83    fi
84done
85
86#   initial command line handling
87if [ $# -eq 0 ]; then
88    echo "$0:Error: invalid command line" 1>&2
89    echo "$0:Hint:  run \`$0 -h' for usage" 1>&2
90    exit 1
91fi
92if [ ".$1" = ".-h" ] || [ ".$1" = ".--help" ]; then
93    echo "This is GNU shtool, version 2.0.6 (19-Apr-2006)"
94    echo 'Copyright (c) 1994-2006 Ralf S. Engelschall <rse@engelschall.com>'
95    echo 'Report bugs to <bug-shtool@gnu.org>'
96    echo ''
97    echo 'Usage: shtool [<options>] [<cmd-name> [<cmd-options>] [<cmd-args>]]'
98    echo ''
99    echo 'Available global <options>:'
100    echo '  -v, --version   display shtool version information'
101    echo '  -h, --help      display shtool usage help page (this one)'
102    echo '  -d, --debug     display shell trace information'
103    echo '  -r, --recreate  recreate this shtool script via shtoolize'
104    echo ''
105    echo 'Available <cmd-name> [<cmd-options>] [<cmd-args>]:'
106    echo '  echo     [-n|--newline] [-e|--expand] [<string> ...]'
107    echo '  mdate    [-n|--newline] [-z|--zero] [-s|--shorten] [-d|--digits]'
108    echo '           [-f|--field-sep <str>] [-o|--order <spec>] <path>'
109    echo '  table    [-F|--field-sep <sep>] [-w|--width <width>] [-c|--columns'
110    echo '           <cols>] [-s|--strip <strip>] <str><sep><str>...'
111    echo '  prop     [-p|--prefix <str>]'
112    echo '  move     [-v|--verbose] [-t|--trace] [-e|--expand] [-p|--preserve]'
113    echo '           <src-file> <dst-file>'
114    echo '  install  [-v|--verbose] [-t|--trace] [-d|--mkdir] [-c|--copy]'
115    echo '           [-C|--compare-copy] [-s|--strip] [-m|--mode <mode>]'
116    echo '           [-o|--owner <owner>] [-g|--group <group>] [-e|--exec'
117    echo '           <sed-cmd>] <file> [<file> ...] <path>'
118    echo '  mkdir    [-t|--trace] [-f|--force] [-p|--parents] [-m|--mode'
119    echo '           <mode>] [-o|--owner <owner>] [-g|--group <group>] <dir>'
120    echo '           [<dir> ...]'
121    echo '  mkln     [-t|--trace] [-f|--force] [-s|--symbolic] <src-path>'
122    echo '           [<src-path> ...] <dst-path>'
123    echo '  mkshadow [-v|--verbose] [-t|--trace] [-a|--all] <src-dir> <dst-dir>'
124    echo '  fixperm  [-v|--verbose] [-t|--trace] <path> [<path> ...]'
125    echo '  rotate   [-v|--verbose] [-t|--trace] [-f|--force] [-n|--num-files'
126    echo '           <count>] [-s|--size <size>] [-c|--copy] [-r|--remove]'
127    echo '           [-a|--archive-dir <dir>] [-z|--compress [<tool>:]<level>]'
128    echo '           [-b|--background] [-d|--delay] [-p|--pad <len>] [-m|--mode'
129    echo '           <mode>] [-o|--owner <owner>] [-g|--group <group>] [-M|--migrate'
130    echo '           <cmd>] [-P|--prolog <cmd>] [-E|--epilog <cmd>] <file> [...]'
131    echo '  tarball  [-t|--trace] [-v|--verbose] [-o|--output <tarball>]'
132    echo '           [-c|--compress <prog>] [-d|--directory <dir>] [-u|--user'
133    echo '           <user>] [-g|--group <group>] [-e|--exclude <pattern>]'
134    echo '           <path> [<path> ...]'
135    echo '  subst    [-v|--verbose] [-t|--trace] [-n|--nop] [-w|--warning]'
136    echo '           [-q|--quiet] [-s|--stealth] [-i|--interactive] [-b|--backup'
137    echo '           <ext>] [-e|--exec <cmd>] [-f|--file <cmd-file>] [<file>]'
138    echo '           [...]'
139    echo '  platform [-F|--format <format>] [-S|--sep <string>] [-C|--conc'
140    echo '           <string>] [-L|--lower] [-U|--upper] [-v|--verbose]'
141    echo '           [-c|--concise] [-n|--no-newline] [-t|--type <type>]'
142    echo '           [-V|--version] [-h|--help]'
143    echo '  arx      [-t|--trace] [-C|--command <cmd>] <op> <archive> [<file>'
144    echo '           ...]'
145    echo '  slo      [-p|--prefix <str>] -- -L<dir> -l<lib> [-L<dir> -l<lib>'
146    echo '           ...]'
147    echo '  scpp     [-v|--verbose] [-p|--preserve] [-f|--filter <filter>]'
148    echo '           [-o|--output <ofile>] [-t|--template <tfile>] [-M|--mark'
149    echo '           <mark>] [-D|--define <dname>] [-C|--class <cname>]'
150    echo '           <file> [<file> ...]'
151    echo '  version  [-l|--language <lang>] [-n|--name <name>] [-p|--prefix'
152    echo '           <prefix>] [-s|--set <version>] [-e|--edit] [-i|--increase'
153    echo '           <knob>] [-d|--display <type>] <file>'
154    echo '  path     [-s|--suppress] [-r|--reverse] [-d|--dirname] [-b|--basename]'
155    echo '           [-m|--magic] [-p|--path <path>] <str> [<str> ...]'
156    echo ''
157    exit 0
158fi
159if [ ".$1" = ".-v" ] || [ ".$1" = ".--version" ]; then
160    echo "GNU shtool 2.0.6 (19-Apr-2006)"
161    exit 0
162fi
163if [ ".$1" = ".-r" ] || [ ".$1" = ".--recreate" ]; then
164    shtoolize -oshtool all
165    exit 0
166fi
167if [ ".$1" = ".-d" ] || [ ".$1" = ".--debug" ]; then
168    shift
169    set -x
170fi
171name=`echo "$0" | sed -e 's;.*/\([^/]*\)$;\1;' -e 's;-sh$;;' -e 's;\.sh$;;'`
172case "$name" in
173    echo|mdate|table|prop|move|install|mkdir|mkln|mkshadow|fixperm|rotate|tarball|subst|platform|arx|slo|scpp|version|path )
174        #   implicit tool command selection
175        tool="$name"
176        ;;
177    * )
178        #   explicit tool command selection
179        tool="$1"
180        shift
181        ;;
182esac
183arg_spec=""
184opt_spec=""
185gen_tmpfile=no
186
187##
188##  DISPATCH INTO SCRIPT PROLOG
189##
190
191case $tool in
192    echo )
193        str_tool="echo"
194        str_usage="[-n|--newline] [-e|--expand] [<string> ...]"
195        arg_spec="0+"
196        opt_spec="n.e."
197        opt_alias="n:newline,e:expand"
198        opt_n=no
199        opt_e=no
200        ;;
201    mdate )
202        str_tool="mdate"
203        str_usage="[-n|--newline] [-z|--zero] [-s|--shorten] [-d|--digits] [-f|--field-sep <str>] [-o|--order <spec>] <path>"
204        arg_spec="1="
205        opt_spec="n.z.s.d.f:o:"
206        opt_alias="n:newline,z:zero,s:shorten,d:digits,f:field-sep,o:order"
207        opt_n=no
208        opt_z=no
209        opt_s=no
210        opt_d=no
211        opt_f=" "
212        opt_o="dmy"
213        ;;
214    table )
215        str_tool="table"
216        str_usage="[-F|--field-sep <sep>] [-w|--width <width>] [-c|--columns <cols>] [-s|--strip <strip>] <str><sep><str>..."
217        arg_spec="1+"
218        opt_spec="F:w:c:s:"
219        opt_alias="F:field-sep,w:width,c:columns,s:strip"
220        opt_F=":"
221        opt_w=15
222        opt_c=3
223        opt_s=79
224        ;;
225    prop )
226        str_tool="prop"
227        str_usage="[-p|--prefix <str>]"
228        arg_spec="0="
229        opt_spec="p:"
230        opt_alias="p:prefix"
231        opt_p=""
232        ;;
233    move )
234        str_tool="move"
235        str_usage="[-v|--verbose] [-t|--trace] [-e|--expand] [-p|--preserve] <src-file> <dst-file>"
236        arg_spec="2="
237        opt_spec="v.t.e.p."
238        opt_alias="v:verbose,t:trace,e:expand,p:preserve"
239        opt_v=no
240        opt_t=no
241        opt_e=no
242        opt_p=no
243        ;;
244    install )
245        str_tool="install"
246        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>"
247        arg_spec="1+"
248        opt_spec="v.t.d.c.C.s.m:o:g:e+"
249        opt_alias="v:verbose,t:trace,d:mkdir,c:copy,C:compare-copy,s:strip,m:mode,o:owner,g:group,e:exec"
250        opt_v=no
251        opt_t=no
252        opt_d=no
253        opt_c=no
254        opt_C=no
255        opt_s=no
256        opt_m="0755"
257        opt_o=""
258        opt_g=""
259        opt_e=""
260        ;;
261    mkdir )
262        str_tool="mkdir"
263        str_usage="[-t|--trace] [-f|--force] [-p|--parents] [-m|--mode <mode>] [-o|--owner <owner>] [-g|--group <group>] <dir> [<dir> ...]"
264        arg_spec="1+"
265        opt_spec="t.f.p.m:o:g:"
266        opt_alias="t:trace,f:force,p:parents,m:mode,o:owner,g:group"
267        opt_t=no
268        opt_f=no
269        opt_p=no
270        opt_m=""
271        opt_o=""
272        opt_g=""
273        ;;
274    mkln )
275        str_tool="mkln"
276        str_usage="[-t|--trace] [-f|--force] [-s|--symbolic] <src-path> [<src-path> ...] <dst-path>"
277        arg_spec="2+"
278        opt_spec="t.f.s."
279        opt_alias="t:trace,f:force,s:symbolic"
280        opt_t=no
281        opt_f=no
282        opt_s=no
283        ;;
284    mkshadow )
285        str_tool="mkshadow"
286        str_usage="[-v|--verbose] [-t|--trace] [-a|--all] <src-dir> <dst-dir>"
287        arg_spec="2="
288        opt_spec="v.t.a."
289        opt_alias="v:verbose,t:trace,a:all"
290        opt_v=no
291        opt_t=no
292        opt_a=no
293        ;;
294    fixperm )
295        str_tool="fixperm"
296        str_usage="[-v|--verbose] [-t|--trace] <path> [<path> ...]"
297        arg_spec="1+"
298        opt_spec="v.t."
299        opt_alias="v:verbose,t:trace"
300        opt_v=no
301        opt_t=no
302        ;;
303    rotate )
304        str_tool="rotate"
305        str_usage="[-v|--verbose] [-t|--trace] [-f|--force] [-n|--num-files <count>] [-s|--size <size>] [-c|--copy] [-r|--remove] [-a|--archive-dir <dir>] [-z|--compress [<tool>:]<level>] [-b|--background] [-d|--delay] [-p|--pad <len>] [-m|--mode <mode>] [-o|--owner <owner>] [-g|--group <group>] [-M|--migrate <cmd>] [-P|--prolog <cmd>] [-E|--epilog <cmd>] <file> [...]"
306        arg_spec="1+"
307        opt_spec="v.t.f.n:s:c.r.a:z:b.d.p:o:g:m:M:P:E:"
308        opt_alias="v:verbose,t:trace,f:force,n:num-files,s:size,c:copy,r:remove,a:archive-dir,z:compress,b:background,d:delay,p:pad,o:owner,g:group,m:mode,M:migrate,P:prolog,E:epilog"
309        opt_v=no
310        opt_t=no
311        opt_f=no
312        opt_n=10
313        opt_s=""
314        opt_c=no
315        opt_r=no
316        opt_a=""
317        opt_z=""
318        opt_b=no
319        opt_d=no
320        opt_p=1
321        opt_o=""
322        opt_g=""
323        opt_m=""
324        opt_M=""
325        opt_P=""
326        opt_E=""
327        ;;
328    tarball )
329        str_tool="tarball"
330        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> ...]"
331        gen_tmpfile=yes
332        arg_spec="1+"
333        opt_spec="t.v.o:c:d:u:g:e:"
334        opt_alias="t:trace,v:verbose,o:output,c:compress,d:directory,u:user,g:group,e:exclude"
335        opt_t=no
336        opt_v=no
337        opt_o=""
338        opt_c=""
339        opt_d=""
340        opt_u=""
341        opt_g=""
342        opt_e="CVS,\\.cvsignore,\\.svn,\\.[oa]\$"
343        ;;
344    subst )
345        str_tool="subst"
346        str_usage="[-v|--verbose] [-t|--trace] [-n|--nop] [-w|--warning] [-q|--quiet] [-s|--stealth] [-i|--interactive] [-b|--backup <ext>] [-e|--exec <cmd>] [-f|--file <cmd-file>] [<file>] [...]"
347        gen_tmpfile=yes
348        arg_spec="0+"
349        opt_spec="v.t.n.w.q.s.i.b:e+f:"
350        opt_alias="v:verbose,t:trace,n:nop,w:warning,q:quiet,s:stealth,i:interactive,b:backup,e:exec,f:file"
351        opt_v=no
352        opt_t=no
353        opt_n=no
354        opt_w=no
355        opt_q=no
356        opt_s=no
357        opt_i=no
358        opt_b=""
359        opt_e=""
360        opt_f=""
361        ;;
362    platform )
363        str_tool="platform"
364        str_usage="[-F|--format <format>] [-S|--sep <string>] [-C|--conc <string>] [-L|--lower] [-U|--upper] [-v|--verbose] [-c|--concise] [-n|--no-newline] [-t|--type <type>] [-V|--version] [-h|--help]"
365        arg_spec="0="
366        opt_spec="F:S:C:L.U.v.c.n.t:d.V.h."
367        opt_alias="F:format,S:sep,C:conc,L:lower,U:upper,v:verbose,c:consise,t:type,n:no-newline,V:version,h:help"
368        opt_F="%{sp} (%{ap})"
369        opt_S=" "
370        opt_C="/"
371        opt_L=no
372        opt_U=no
373        opt_t=""
374        opt_v=no
375        opt_c=no
376        opt_n=no
377        opt_V=no
378        opt_h=no
379        ;;
380    arx )
381        str_tool="arx"
382        str_usage="[-t|--trace] [-C|--command <cmd>] <op> <archive> [<file> ...]"
383        arg_spec="2+"
384        opt_spec="t.C:"
385        opt_alias="t:trace,C:command"
386        opt_t=no
387        opt_C="ar"
388        ;;
389    slo )
390        str_tool="slo"
391        str_usage="[-p|--prefix <str>] -- -L<dir> -l<lib> [-L<dir> -l<lib> ...]"
392        arg_spec="1+"
393        opt_spec="p:"
394        opt_alias="p:prefix"
395        opt_p="SLO_"
396        ;;
397    scpp )
398        str_tool="scpp"
399        str_usage="[-v|--verbose] [-p|--preserve] [-f|--filter <filter>] [-o|--output <ofile>] [-t|--template <tfile>] [-M|--mark <mark>] [-D|--define <dname>] [-C|--class <cname>] <file> [<file> ...]"
400        gen_tmpfile=yes
401        arg_spec="1+"
402        opt_spec="v.p.f+o:t:M:D:C:"
403        opt_alias="v:verbose,p:preserve,f:filter,o:output,t:template,M:mark,D:define,C:class"
404        opt_v=no
405        opt_p=no
406        opt_f=""
407        opt_o="lib.h"
408        opt_t="lib.h.in"
409        opt_M="%%MARK%%"
410        opt_D="cpp"
411        opt_C="intern"
412        ;;
413    version )
414        str_tool="version"
415        str_usage="[-l|--language <lang>] [-n|--name <name>] [-p|--prefix <prefix>] [-s|--set <version>] [-e|--edit] [-i|--increase <knob>] [-d|--display <type>] <file>"
416        arg_spec="1="
417        opt_spec="l:n:p:s:i:e.d:"
418        opt_alias="l:language,n:name,p:prefix,s:set,e:edit,i:increase,d:display"
419        opt_l="txt"
420        opt_n="unknown"
421        opt_p=""
422        opt_s=""
423        opt_e="no"
424        opt_i=""
425        opt_d="short"
426        ;;
427    path )
428        str_tool="path"
429        str_usage="[-s|--suppress] [-r|--reverse] [-d|--dirname] [-b|--basename] [-m|--magic] [-p|--path <path>] <str> [<str> ...]"
430        gen_tmpfile=yes
431        arg_spec="1+"
432        opt_spec="s.r.d.b.m.p:"
433        opt_alias="s:suppress,r:reverse,d:dirname,b:basename,m:magic,p:path"
434        opt_s=no
435        opt_r=no
436        opt_d=no
437        opt_b=no
438        opt_m=no
439        opt_p="$PATH"
440        ;;
441    -* )
442        echo "$0:Error: unknown option \`$tool'" 2>&1
443        echo "$0:Hint:  run \`$0 -h' for usage" 2>&1
444        exit 1
445        ;;
446    * )
447        echo "$0:Error: unknown command \`$tool'" 2>&1
448        echo "$0:Hint:  run \`$0 -h' for usage" 2>&1
449        exit 1
450        ;;
451esac
452
453##
454##  COMMON UTILITY CODE
455##
456
457#   commonly used ASCII values
458ASC_TAB="	"
459ASC_NL="
460"
461
462#   determine name of tool
463if [ ".$tool" != . ]; then
464    #   used inside shtool script
465    toolcmd="$0 $tool"
466    toolcmdhelp="shtool $tool"
467    msgprefix="shtool:$tool"
468else
469    #   used as standalone script
470    toolcmd="$0"
471    toolcmdhelp="sh $0"
472    msgprefix="$str_tool"
473fi
474
475#   parse argument specification string
476eval `echo $arg_spec |\
477      sed -e 's/^\([0-9]*\)\([+=]\)/arg_NUMS=\1; arg_MODE=\2/'`
478
479#   parse option specification string
480eval `echo h.$opt_spec |\
481      sed -e 's/\([a-zA-Z0-9]\)\([.:+]\)/opt_MODE_\1=\2;/g'`
482
483#   parse option alias string
484eval `echo h:help,$opt_alias |\
485      sed -e 's/-/_/g' -e 's/\([a-zA-Z0-9]\):\([^,]*\),*/opt_ALIAS_\2=\1;/g'`
486
487#   interate over argument line
488opt_PREV=''
489while [ $# -gt 0 ]; do
490    #   special option stops processing
491    if [ ".$1" = ".--" ]; then
492        shift
493        break
494    fi
495
496    #   determine option and argument
497    opt_ARG_OK=no
498    if [ ".$opt_PREV" != . ]; then
499        #   merge previous seen option with argument
500        opt_OPT="$opt_PREV"
501        opt_ARG="$1"
502        opt_ARG_OK=yes
503        opt_PREV=''
504    else
505        #   split argument into option and argument
506        case "$1" in
507            --[a-zA-Z0-9]*=*)
508                eval `echo "x$1" |\
509                      sed -e 's/^x--\([a-zA-Z0-9-]*\)=\(.*\)$/opt_OPT="\1";opt_ARG="\2"/'`
510                opt_STR=`echo $opt_OPT | sed -e 's/-/_/g'`
511                eval "opt_OPT=\${opt_ALIAS_${opt_STR}-${opt_OPT}}"
512                ;;
513            --[a-zA-Z0-9]*)
514                opt_OPT=`echo "x$1" | cut -c4-`
515                opt_STR=`echo $opt_OPT | sed -e 's/-/_/g'`
516                eval "opt_OPT=\${opt_ALIAS_${opt_STR}-${opt_OPT}}"
517                opt_ARG=''
518                ;;
519            -[a-zA-Z0-9]*)
520                eval `echo "x$1" |\
521                      sed -e 's/^x-\([a-zA-Z0-9]\)/opt_OPT="\1";/' \
522                          -e 's/";\(.*\)$/"; opt_ARG="\1"/'`
523                ;;
524            -[a-zA-Z0-9])
525                opt_OPT=`echo "x$1" | cut -c3-`
526                opt_ARG=''
527                ;;
528            *)
529                break
530                ;;
531        esac
532    fi
533
534    #   eat up option
535    shift
536
537    #   determine whether option needs an argument
538    eval "opt_MODE=\$opt_MODE_${opt_OPT}"
539    if [ ".$opt_ARG" = . ] && [ ".$opt_ARG_OK" != .yes ]; then
540        if [ ".$opt_MODE" = ".:" ] || [ ".$opt_MODE" = ".+" ]; then
541            opt_PREV="$opt_OPT"
542            continue
543        fi
544    fi
545
546    #   process option
547    case $opt_MODE in
548        '.' )
549            #   boolean option
550            eval "opt_${opt_OPT}=yes"
551            ;;
552        ':' )
553            #   option with argument (multiple occurances override)
554            eval "opt_${opt_OPT}=\"\$opt_ARG\""
555            ;;
556        '+' )
557            #   option with argument (multiple occurances append)
558            eval "opt_${opt_OPT}=\"\$opt_${opt_OPT}\${ASC_NL}\$opt_ARG\""
559            ;;
560        * )
561            echo "$msgprefix:Error: unknown option: \`$opt_OPT'" 1>&2
562            echo "$msgprefix:Hint:  run \`$toolcmdhelp -h' or \`man shtool' for details" 1>&2
563            exit 1
564            ;;
565    esac
566done
567if [ ".$opt_PREV" != . ]; then
568    echo "$msgprefix:Error: missing argument to option \`$opt_PREV'" 1>&2
569    echo "$msgprefix:Hint:  run \`$toolcmdhelp -h' or \`man shtool' for details" 1>&2
570    exit 1
571fi
572
573#   process help option
574if [ ".$opt_h" = .yes ]; then
575    echo "Usage: $toolcmdhelp $str_usage"
576    exit 0
577fi
578
579#   complain about incorrect number of arguments
580case $arg_MODE in
581    '=' )
582        if [ $# -ne $arg_NUMS ]; then
583            echo "$msgprefix:Error: invalid number of arguments (exactly $arg_NUMS expected)" 1>&2
584            echo "$msgprefix:Hint:  run \`$toolcmd -h' or \`man shtool' for details" 1>&2
585            exit 1
586        fi
587        ;;
588    '+' )
589        if [ $# -lt $arg_NUMS ]; then
590            echo "$msgprefix:Error: invalid number of arguments (at least $arg_NUMS expected)" 1>&2
591            echo "$msgprefix:Hint:  run \`$toolcmd -h' or \`man shtool' for details" 1>&2
592            exit 1
593        fi
594        ;;
595esac
596
597#   establish a temporary file on request
598if [ ".$gen_tmpfile" = .yes ]; then
599    #   create (explicitly) secure temporary directory
600    if [ ".$TMPDIR" != . ]; then
601        tmpdir="$TMPDIR"
602    elif [ ".$TEMPDIR" != . ]; then
603        tmpdir="$TEMPDIR"
604    else
605        tmpdir="/tmp"
606    fi
607    tmpdir="$tmpdir/.shtool.$$"
608    ( umask 077
609      rm -rf "$tmpdir" >/dev/null 2>&1 || true
610      mkdir  "$tmpdir" >/dev/null 2>&1
611      if [ $? -ne 0 ]; then
612          echo "$msgprefix:Error: failed to create temporary directory \`$tmpdir'" 1>&2
613          exit 1
614      fi
615    )
616
617    #   create (implicitly) secure temporary file
618    tmpfile="$tmpdir/shtool.tmp"
619    touch "$tmpfile"
620fi
621
622#   utility function: map string to lower case
623util_lower () {
624    echo "$1" | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'
625}
626
627#   utility function: map string to upper case
628util_upper () {
629    echo "$1" | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
630}
631
632#   cleanup procedure
633shtool_exit () {
634    rc="$1"
635    if [ ".$gen_tmpfile" = .yes ]; then
636        rm -rf "$tmpdir" >/dev/null 2>&1 || true
637    fi
638    exit $rc
639}
640
641##
642##  DISPATCH INTO SCRIPT BODY
643##
644
645case $tool in
646
647echo )
648    ##
649    ##  echo -- Print string with optional construct expansion
650    ##  Copyright (c) 1998-2006 Ralf S. Engelschall <rse@engelschall.com>
651    ##
652
653    text="$*"
654
655    #   check for broken escape sequence expansion
656    seo=''
657    bytes=`echo '\1' | wc -c | awk '{ printf("%s", $1); }'`
658    if [ ".$bytes" != .3 ]; then
659        bytes=`echo -E '\1' | wc -c | awk '{ printf("%s", $1); }'`
660        if [ ".$bytes" = .3 ]; then
661            seo='-E'
662        fi
663    fi
664
665    #   check for existing -n option (to suppress newline)
666    minusn=''
667    bytes=`echo -n 123 2>/dev/null | wc -c | awk '{ printf("%s", $1); }'`
668    if [ ".$bytes" = .3 ]; then
669        minusn='-n'
670    fi
671
672    #   determine terminal bold sequence
673    term_bold=''
674    term_norm=''
675    if [ ".$opt_e" = .yes ] && [ ".`echo $text | grep '%[Bb]'`" != . ]; then
676        case $TERM in
677            #   for the most important terminal types we directly know the sequences
678            xterm|xterm*|vt220|vt220*)
679                term_bold=`awk 'BEGIN { printf("%c%c%c%c", 27, 91, 49, 109); }' </dev/null 2>/dev/null`
680                term_norm=`awk 'BEGIN { printf("%c%c%c", 27, 91, 109); }' </dev/null 2>/dev/null`
681                ;;
682            vt100|vt100*|cygwin)
683                term_bold=`awk 'BEGIN { printf("%c%c%c%c%c%c", 27, 91, 49, 109, 0, 0); }' </dev/null 2>/dev/null`
684                term_norm=`awk 'BEGIN { printf("%c%c%c%c%c", 27, 91, 109, 0, 0); }' </dev/null 2>/dev/null`
685                ;;
686            #   for all others, we try to use a possibly existing `tput' or `tcout' utility
687            * )
688                paths=`echo $PATH | sed -e 's/:/ /g'`
689                for tool in tput tcout; do
690                    for dir in $paths; do
691                        if [ -r "$dir/$tool" ]; then
692                            for seq in bold md smso; do # 'smso' is last
693                                bold="`$dir/$tool $seq 2>/dev/null`"
694                                if [ ".$bold" != . ]; then
695                                    term_bold="$bold"
696                                    break
697                                fi
698                            done
699                            if [ ".$term_bold" != . ]; then
700                                for seq in sgr0 me rmso init reset; do # 'reset' is last
701                                    norm="`$dir/$tool $seq 2>/dev/null`"
702                                    if [ ".$norm" != . ]; then
703                                        term_norm="$norm"
704                                        break
705                                    fi
706                                done
707                            fi
708                            break
709                        fi
710                    done
711                    if [ ".$term_bold" != . ] && [ ".$term_norm" != . ]; then
712                        break;
713                    fi
714                done
715                ;;
716        esac
717        if [ ".$term_bold" = . ] || [ ".$term_norm" = . ]; then
718            echo "$msgprefix:Warning: unable to determine terminal sequence for bold mode" 1>&2
719            term_bold=''
720            term_norm=''
721        fi
722    fi
723
724    #   determine user name
725    username=''
726    if [ ".$opt_e" = .yes ] && [ ".`echo $text | grep '%[uUgG]'`" != . ]; then
727        username="`(id -un) 2>/dev/null`"
728        if [ ".$username" = . ]; then
729            str="`(id) 2>/dev/null`"
730            if [ ".`echo $str | grep '^uid[ 	]*=[ 	]*[0-9]*('`" != . ]; then
731                username=`echo $str | sed -e 's/^uid[ 	]*=[ 	]*[0-9]*(//' -e 's/).*$//'`
732            fi
733            if [ ".$username" = . ]; then
734                username="$LOGNAME"
735                if [ ".$username" = . ]; then
736                    username="$USER"
737                    if [ ".$username" = . ]; then
738                        username="`(whoami) 2>/dev/null |\
739                                   awk '{ printf("%s", $1); }'`"
740                        if [ ".$username" = . ]; then
741                            username="`(who am i) 2>/dev/null |\
742                                       awk '{ printf("%s", $1); }'`"
743                            if [ ".$username" = . ]; then
744                                username='unknown'
745                            fi
746                        fi
747                    fi
748                fi
749            fi
750        fi
751    fi
752
753    #   determine user id
754    userid=''
755    if [ ".$opt_e" = .yes ] && [ ".`echo $text | grep '%U'`" != . ]; then
756        userid="`(id -u) 2>/dev/null`"
757        if [ ".$userid" = . ]; then
758            userid="`(id -u ${username}) 2>/dev/null`"
759            if [ ".$userid" = . ]; then
760                str="`(id) 2>/dev/null`"
761                if [ ".`echo $str | grep '^uid[ 	]*=[ 	]*[0-9]*('`" != . ]; then
762                    userid=`echo $str | sed -e 's/^uid[ 	]*=[ 	]*//' -e 's/(.*$//'`
763                fi
764                if [ ".$userid" = . ]; then
765                    userid=`(getent passwd ${username}) 2>/dev/null | \
766                            sed -e 's/[^:]*:[^:]*://' -e 's/:.*$//'`
767                    if [ ".$userid" = . ]; then
768                        userid=`grep "^${username}:" /etc/passwd 2>/dev/null | \
769                                sed -e 's/[^:]*:[^:]*://' -e 's/:.*$//'`
770                        if [ ".$userid" = . ]; then
771                            userid=`(ypcat passwd) 2>/dev/null |
772                                    grep "^${username}:" | \
773                                    sed -e 's/[^:]*:[^:]*://' -e 's/:.*$//'`
774                            if [ ".$userid" = . ]; then
775                                userid='?'
776                            fi
777                        fi
778                    fi
779                fi
780            fi
781        fi
782    fi
783
784    #   determine (primary) group id
785    groupid=''
786    if [ ".$opt_e" = .yes ] && [ ".`echo $text | grep '%[gG]'`" != . ]; then
787        groupid="`(id -g ${username}) 2>/dev/null`"
788        if [ ".$groupid" = . ]; then
789            str="`(id) 2>/dev/null`"
790            if [ ".`echo $str | grep 'gid[ 	]*=[ 	]*[0-9]*('`" != . ]; then
791                groupid=`echo $str | sed -e 's/^.*gid[ 	]*=[ 	]*//' -e 's/(.*$//'`
792            fi
793            if [ ".$groupid" = . ]; then
794                groupid=`(getent passwd ${username}) 2>/dev/null | \
795                         sed -e 's/[^:]*:[^:]*:[^:]*://' -e 's/:.*$//'`
796                if [ ".$groupid" = . ]; then
797                    groupid=`grep "^${username}:" /etc/passwd 2>/dev/null | \
798                             sed -e 's/[^:]*:[^:]*:[^:]*://' -e 's/:.*$//'`
799                    if [ ".$groupid" = . ]; then
800                        groupid=`(ypcat passwd) 2>/dev/null | grep "^${username}:" | \
801                                 sed -e 's/[^:]*:[^:]*:[^:]*://' -e 's/:.*$//'`
802                        if [ ".$groupid" = . ]; then
803                            groupid='?'
804                        fi
805                    fi
806                fi
807            fi
808        fi
809    fi
810
811    #   determine (primary) group name
812    groupname=''
813    if [ ".$opt_e" = .yes ] && [ ".`echo $text | grep '%g'`" != . ]; then
814        groupname="`(id -gn ${username}) 2>/dev/null`"
815        if [ ".$groupname" = . ]; then
816            str="`(id) 2>/dev/null`"
817            if [ ".`echo $str | grep 'gid[ 	]*=[ 	]*[0-9]*('`" != . ]; then
818                groupname=`echo $str | sed -e 's/^.*gid[ 	]*=[ 	]*[0-9]*(//' -e 's/).*$//'`
819            fi
820            if [ ".$groupname" = . ]; then
821                groupname=`(getent group) 2>/dev/null | \
822                           grep "^[^:]*:[^:]*:${groupid}:" | \
823                           sed -e 's/:.*$//'`
824                if [ ".$groupname" = . ]; then
825                    groupname=`grep "^[^:]*:[^:]*:${groupid}:" /etc/group 2>/dev/null | \
826                               sed -e 's/:.*$//'`
827                    if [ ".$groupname" = . ]; then
828                        groupname=`(ypcat group) 2>/dev/null | \
829                                   grep "^[^:]*:[^:]*:${groupid}:" | \
830                                   sed -e 's/:.*$//'`
831                        if [ ".$groupname" = . ]; then
832                            groupname='?'
833                        fi
834                    fi
835                fi
836            fi
837        fi
838    fi
839
840    #   determine host and domain name
841    hostname=''
842    domainname=''
843    if [ ".$opt_e" = .yes ] && [ ".`echo $text | grep '%h'`" != . ]; then
844        hostname="`(uname -n) 2>/dev/null |\
845                   awk '{ printf("%s", $1); }'`"
846        if [ ".$hostname" = . ]; then
847            hostname="`(hostname) 2>/dev/null |\
848                       awk '{ printf("%s", $1); }'`"
849            if [ ".$hostname" = . ]; then
850                hostname='unknown'
851            fi
852        fi
853        case $hostname in
854            *.* )
855                domainname=".`echo $hostname | cut -d. -f2-`"
856                hostname="`echo $hostname | cut -d. -f1`"
857                ;;
858        esac
859    fi
860    if [ ".$opt_e" = .yes ] && [ ".`echo $text | grep '%d'`" != . ]; then
861        if [ ".$domainname" = . ]; then
862            if [ -f /etc/resolv.conf ]; then
863                domainname="`grep '^[ 	]*domain' /etc/resolv.conf | sed -e 'q' |\
864                             sed -e 's/.*domain//' \
865                                 -e 's/^[ 	]*//' -e 's/^ *//' -e 's/^	*//' \
866                                 -e 's/^\.//' -e 's/^/./' |\
867                             awk '{ printf("%s", $1); }'`"
868                if [ ".$domainname" = . ]; then
869                    domainname="`grep '^[ 	]*search' /etc/resolv.conf | sed -e 'q' |\
870                                 sed -e 's/.*search//' \
871                                     -e 's/^[ 	]*//' -e 's/^ *//' -e 's/^	*//' \
872                                     -e 's/ .*//' -e 's/	.*//' \
873                                     -e 's/^\.//' -e 's/^/./' |\
874                                 awk '{ printf("%s", $1); }'`"
875                fi
876            fi
877        fi
878    fi
879
880    #   determine current time
881    time_day=''
882    time_month=''
883    time_year=''
884    time_monthname=''
885    if [ ".$opt_e" = .yes ] && [ ".`echo $text | grep '%[DMYm]'`" != . ]; then
886        time_day=`date '+%d'`
887        time_month=`date '+%m'`
888        time_year=`date '+%Y' 2>/dev/null`
889        if [ ".$time_year" = . ]; then
890            time_year=`date '+%y'`
891            case $time_year in
892                [5-9][0-9]) time_year="19$time_year" ;;
893                [0-4][0-9]) time_year="20$time_year" ;;
894            esac
895        fi
896        case $time_month in
897            1|01) time_monthname='Jan' ;;
898            2|02) time_monthname='Feb' ;;
899            3|03) time_monthname='Mar' ;;
900            4|04) time_monthname='Apr' ;;
901            5|05) time_monthname='May' ;;
902            6|06) time_monthname='Jun' ;;
903            7|07) time_monthname='Jul' ;;
904            8|08) time_monthname='Aug' ;;
905            9|09) time_monthname='Sep' ;;
906              10) time_monthname='Oct' ;;
907              11) time_monthname='Nov' ;;
908              12) time_monthname='Dec' ;;
909        esac
910    fi
911
912    #   expand special ``%x'' constructs
913    if [ ".$opt_e" = .yes ]; then
914        text=`echo $seo "$text" |\
915              sed -e "s/%B/${term_bold}/g" \
916                  -e "s/%b/${term_norm}/g" \
917                  -e "s/%u/${username}/g" \
918                  -e "s/%U/${userid}/g" \
919                  -e "s/%g/${groupname}/g" \
920                  -e "s/%G/${groupid}/g" \
921                  -e "s/%h/${hostname}/g" \
922                  -e "s/%d/${domainname}/g" \
923                  -e "s/%D/${time_day}/g" \
924                  -e "s/%M/${time_month}/g" \
925                  -e "s/%Y/${time_year}/g" \
926                  -e "s/%m/${time_monthname}/g" 2>/dev/null`
927    fi
928
929    #   create output
930    if [ .$opt_n = .no ]; then
931        echo $seo "$text"
932    else
933        #   the harder part: echo -n is best, because
934        #   awk may complain about some \xx sequences.
935        if [ ".$minusn" != . ]; then
936            echo $seo $minusn "$text"
937        else
938            echo dummy | awk '{ printf("%s", TEXT); }' TEXT="$text"
939        fi
940    fi
941
942    shtool_exit 0
943    ;;
944
945mdate )
946    ##
947    ##  mdate -- Pretty-print modification time of a file or dir
948    ##  Copyright (c) 1995-1997 Free Software Foundation, Inc.
949    ##  Copyright (c) 1998-2006 Ralf S. Engelschall <rse@engelschall.com>
950    ##
951
952    fod="$1"
953    case "$opt_o" in
954        [dmy][dmy][dmy] )
955            ;;
956        * ) echo "$msgprefix:Error: invalid argument to option \`-o': $opt_o" 1>&2
957            shtool_exit 1
958            ;;
959    esac
960    if [ ! -r "$fod" ]; then
961        echo "$msgprefix:Error: file or directory not found: $fod" 1>&2
962        shtool_exit 1
963    fi
964
965    #   GNU ls changes its time format in response to the TIME_STYLE
966    #   variable. Since we cannot assume "unset" works, revert this
967    #   variable to its documented default.
968    if [ ".$TIME_STYLE" != . ]; then
969        TIME_STYLE=posix-long-iso
970        export TIME_STYLE
971    fi
972
973    #   get the extended ls output of the file or directory.
974    if /bin/ls -L /dev/null >/dev/null 2>&1; then
975        set - x`/bin/ls -L -l -d $fod`
976    else
977        set - x`/bin/ls -l -d $fod`
978    fi
979
980    #   The month is at least the fourth argument
981    #   (3 shifts here, the next inside the loop).
982    shift; shift; shift
983
984    #   Find the month. Next argument is day, followed by the year or time.
985    month=""
986    while [ ".$month" = . ]; do
987        shift
988        case $1 in
989            Jan) month=January;   nummonth=1  ;;
990            Feb) month=February;  nummonth=2  ;;
991            Mar) month=March;     nummonth=3  ;;
992            Apr) month=April;     nummonth=4  ;;
993            May) month=May;       nummonth=5  ;;
994            Jun) month=June;      nummonth=6  ;;
995            Jul) month=July;      nummonth=7  ;;
996            Aug) month=August;    nummonth=8  ;;
997            Sep) month=September; nummonth=9  ;;
998            Oct) month=October;   nummonth=10 ;;
999            Nov) month=November;  nummonth=11 ;;
1000            Dec) month=December;  nummonth=12 ;;
1001        esac
1002    done
1003    day="$2"
1004    year="$3"
1005
1006    #   We finally have to deal with the problem that the "ls" output
1007    #   gives either the time of the day or the year.
1008    case $year in
1009        *:*)
1010            this_year=`date '+%Y' 2>/dev/null`
1011            if [ ".$this_year" = . ]; then
1012                this_year=`date '+%y'`
1013                case $this_year in
1014                    [5-9][0-9]) this_year="19$this_year" ;;
1015                    [0-4][0-9]) this_year="20$this_year" ;;
1016                esac
1017            fi
1018            #   for the following months of the last year the time notation
1019            #   is usually also used for files modified in the last year.
1020            this_month=`date '+%m'`
1021            if (expr $nummonth \> $this_month) >/dev/null; then
1022                this_year=`expr $this_year - 1`
1023            fi
1024            year="$this_year"
1025            ;;
1026    esac
1027
1028    #   Optionally fill day and month with leeding zeros
1029    if [ ".$opt_z" = .yes ]; then
1030        case $day in
1031            [0-9][0-9] ) ;;
1032                 [0-9] ) day="0$day" ;;
1033        esac
1034        case $nummonth in
1035            [0-9][0-9] ) ;;
1036                 [0-9] ) nummonth="0$nummonth" ;;
1037        esac
1038    fi
1039
1040    #   Optionally use digits for month
1041    if [ ".$opt_d" = .yes ]; then
1042        month="$nummonth"
1043    fi
1044
1045    #   Optionally shorten the month name to three characters
1046    if [ ".$opt_s" = .yes ]; then
1047        month=`echo $month | cut -c1-3`
1048    fi
1049
1050    #   Output the resulting date string
1051    echo dummy | awk '{
1052        for (i = 0; i < 3; i++) {
1053            now = substr(order, 1, 1);
1054            order = substr(order, 2);
1055            if (now == "d")
1056                out = day;
1057            else if (now == "m")
1058                out = month;
1059            else if (now == "y")
1060                out = year;
1061            if (i < 2)
1062                printf("%s%s", out, field);
1063            else
1064                printf("%s", out);
1065        }
1066        if (newline != "yes")
1067            printf("\n");
1068    }' "day=$day" "month=$month" "year=$year" \
1069       "field=$opt_f" "order=$opt_o" "newline=$opt_n"
1070
1071    shtool_exit 0
1072    ;;
1073
1074table )
1075    ##
1076    ##  table -- Pretty-print a field-separated list as a table
1077    ##  Copyright (c) 1998-2006 Ralf S. Engelschall <rse@engelschall.com>
1078    ##
1079
1080    if [ $opt_c -gt 4 ]; then
1081        echo "$msgprefix:Error: Invalid number of colums (1..4 allowed only)" 1>&2
1082        shtool_exit 1
1083    fi
1084    case "x$opt_F" in
1085        x? ) ;;
1086        *  ) echo "$msgprefix:Error: Invalid separator (one char allowed only)" 1>&2; shtool_exit 1 ;;
1087    esac
1088
1089    #   split the list into a table
1090    list=`
1091        IFS="$opt_F"
1092        for entry in $*; do
1093            if [ ".$entry" != . ]; then
1094                echo "$entry"
1095            fi
1096        done |\
1097        awk "
1098            BEGIN { list = \"\"; n = 0; }
1099            {
1100                list = list \\$1;
1101                n = n + 1;
1102                if (n < $opt_c) {
1103                    list = list \":\";
1104                }
1105                if (n == $opt_c) {
1106                    list = list \"\\n\";
1107                    n = 0;
1108                }
1109            }
1110            END { print list; }
1111         "
1112    `
1113
1114    #   format table cells and make sure table
1115    #   doesn't exceed maximum width
1116    OIFS="$IFS"
1117    IFS='
1118'
1119    for entry in $list; do
1120        case $opt_c in
1121            1 ) eval "echo \"\${entry}\" | awk -F: '{ printf(\"%-${opt_w}s\\n\", \$1); }'" ;;
1122            2 ) eval "echo \"\${entry}\" | awk -F: '{ printf(\"%-${opt_w}s %-${opt_w}s\\n\", \$1, \$2); }'" ;;
1123            3 ) eval "echo \"\${entry}\" | awk -F: '{ printf(\"%-${opt_w}s %-${opt_w}s %-${opt_w}s\\n\", \$1, \$2, \$3); }'" ;;
1124            4 ) eval "echo \"\${entry}\" | awk -F: '{ printf(\"%-${opt_w}s %-${opt_w}s %-${opt_w}s %-${opt_w}s\\n\", \$1, \$2, \$3, \$4); }'" ;;
1125        esac
1126    done |\
1127    awk "{
1128        if (length(\$0) > $opt_s) {
1129            printf(\"%s\\n\", substr(\$0, 0, $opt_s-1));
1130        } else {
1131            print \$0;
1132        }
1133    }"
1134    IFS="$OIFS"
1135
1136    shtool_exit 0
1137    ;;
1138
1139prop )
1140    ##
1141    ##  prop -- Display progress with a running propeller
1142    ##  Copyright (c) 1998-2006 Ralf S. Engelschall <rse@engelschall.com>
1143    ##
1144
1145    perl=''
1146    for dir in `echo $PATH | sed -e 's/:/ /g'` .; do
1147        if [ -f "$dir/perl" ]; then
1148            perl="$dir/perl"
1149            break
1150        fi
1151    done
1152    if [ ".$perl" != . ]; then
1153        #   Perl is preferred because writing to STDERR in
1154        #   Perl really writes immediately as one would expect
1155        $perl -e '
1156            @p = ("|","/","-","\\");
1157            $i = 0;
1158            while (<STDIN>) {
1159                printf(STDERR "\r%s...%s\b", $ARGV[0], $p[$i++]);
1160                $i = 0 if ($i > 3);
1161            }
1162            printf(STDERR "\r%s    \n", $ARGV[0]);
1163        ' "$opt_p"
1164    else
1165        #   But if Perl doesn't exists we use Awk even
1166        #   some Awk's buffer even the /dev/stderr writing :-(
1167        awk '
1168            BEGIN {
1169                split("|#/#-#\\", p, "#");
1170                i = 1;
1171            }
1172            {
1173                printf("\r%s%c\b", prefix, p[i++]) > "/dev/stderr";
1174                if (i > 4) { i = 1; }
1175            }
1176            END {
1177                printf("\r%s    \n", prefix) > "/dev/stderr";
1178            }
1179        ' "prefix=$opt_p"
1180    fi
1181
1182    shtool_exit 0
1183    ;;
1184
1185move )
1186    ##
1187    ##  move -- Move files with simultaneous substitution
1188    ##  Copyright (c) 1999-2006 Ralf S. Engelschall <rse@engelschall.com>
1189    ##
1190
1191    src="$1"
1192    dst="$2"
1193
1194    #   consistency checks
1195    if [ ".$src" = . ] || [ ".$dst" = . ]; then
1196        echo "$msgprefix:Error: Invalid arguments" 1>&2
1197        shtool_exit 1
1198    fi
1199    if [ ".$src" = ".$dst" ]; then
1200        echo "$msgprefix:Error: Source and destination files are the same" 1>&2
1201        shtool_exit 1
1202    fi
1203    expsrc="$src"
1204    if [ ".$opt_e" = .yes ]; then
1205        expsrc="`echo $expsrc`"
1206    fi
1207    if [ ".$opt_e" = .yes ]; then
1208        if [ ".`echo "$src" | sed -e 's;^.*\\*.*$;;'`" = ".$src" ]; then
1209            echo "$msgprefix:Error: Source doesn't contain wildcard ('*'): $dst" 1>&2
1210            shtool_exit 1
1211        fi
1212        if [ ".`echo "$dst" | sed -e 's;^.*%[1-9].*$;;'`" = ".$dst" ]; then
1213            echo "$msgprefix:Error: Destination doesn't contain substitution ('%N'): $dst" 1>&2
1214            shtool_exit 1
1215        fi
1216        if [ ".$expsrc" = ".$src" ]; then
1217            echo "$msgprefix:Error: Sources not found or no asterisk : $src" 1>&2
1218            shtool_exit 1
1219        fi
1220    else
1221        if [ ! -r "$src" ]; then
1222            echo "$msgprefix:Error: Source not found: $src" 1>&2
1223            shtool_exit 1
1224        fi
1225    fi
1226
1227    #   determine substitution patterns
1228    if [ ".$opt_e" = .yes ]; then
1229        srcpat=`echo "$src" | sed -e 's/\\./\\\\./g' -e 's/;/\\;/g' -e 's;\\*;\\\\(.*\\\\);g'`
1230        dstpat=`echo "$dst" | sed -e 's;%\([1-9]\);\\\\\1;g'`
1231    fi
1232
1233    #   iterate over source(s)
1234    for onesrc in $expsrc; do
1235        if [ .$opt_e = .yes ]; then
1236            onedst=`echo $onesrc | sed -e "s;$srcpat;$dstpat;"`
1237        else
1238            onedst="$dst"
1239        fi
1240        errorstatus=0
1241        if [ ".$opt_v" = .yes ]; then
1242            echo "$onesrc -> $onedst"
1243        fi
1244        if [ ".$opt_p" = .yes ]; then
1245            if [ -r $onedst ]; then
1246                if cmp -s $onesrc $onedst; then
1247                    if [ ".$opt_t" = .yes ]; then
1248                        echo "rm -f $onesrc" 1>&2
1249                    fi
1250                    rm -f $onesrc || errorstatus=$?
1251                else
1252                    if [ ".$opt_t" = .yes ]; then
1253                        echo "mv -f $onesrc $onedst" 1>&2
1254                    fi
1255                    mv -f $onesrc $onedst || errorstatus=$?
1256                fi
1257            else
1258                if [ ".$opt_t" = .yes ]; then
1259                    echo "mv -f $onesrc $onedst" 1>&2
1260                fi
1261                mv -f $onesrc $onedst || errorstatus=$?
1262            fi
1263        else
1264            if [ ".$opt_t" = .yes ]; then
1265                echo "mv -f $onesrc $onedst" 1>&2
1266            fi
1267            mv -f $onesrc $onedst || errorstatus=$?
1268        fi
1269        if [ $errorstatus -ne 0 ]; then
1270            break;
1271        fi
1272    done
1273
1274    shtool_exit $errorstatus
1275    ;;
1276
1277install )
1278    ##
1279    ##  install -- Install a program, script or datafile
1280    ##  Copyright (c) 1997-2006 Ralf S. Engelschall <rse@engelschall.com>
1281    ##
1282
1283    #   special case: "shtool install -d <dir> [...]" internally
1284    #   maps to "shtool mkdir -f -p -m 755 <dir> [...]"
1285    if [ "$opt_d" = yes ]; then
1286        cmd="$0 mkdir -f -p -m 755"
1287        if [ ".$opt_o" != . ]; then
1288            cmd="$cmd -o '$opt_o'"
1289        fi
1290        if [ ".$opt_g" != . ]; then
1291            cmd="$cmd -g '$opt_g'"
1292        fi
1293        if [ ".$opt_v" = .yes ]; then
1294            cmd="$cmd -v"
1295        fi
1296        if [ ".$opt_t" = .yes ]; then
1297            cmd="$cmd -t"
1298        fi
1299        for dir in "$@"; do
1300            eval "$cmd $dir" || shtool_exit $?
1301        done
1302        shtool_exit 0
1303    fi
1304
1305    #   determine source(s) and destination
1306    argc=$#
1307    srcs=""
1308    while [ $# -gt 1 ]; do
1309        srcs="$srcs $1"
1310        shift
1311    done
1312    dstpath="$1"
1313
1314    #   type check for destination
1315    dstisdir=0
1316    if [ -d $dstpath ]; then
1317        dstpath=`echo "$dstpath" | sed -e 's:/$::'`
1318        dstisdir=1
1319    fi
1320
1321    #   consistency check for destination
1322    if [ $argc -gt 2 ] && [ $dstisdir = 0 ]; then
1323        echo "$msgprefix:Error: multiple sources require destination to be directory" 1>&2
1324        shtool_exit 1
1325    fi
1326
1327    #   iterate over all source(s)
1328    for src in $srcs; do
1329        dst=$dstpath
1330
1331        #   if destination is a directory, append the input filename
1332        if [ $dstisdir = 1 ]; then
1333            dstfile=`echo "$src" | sed -e 's;.*/\([^/]*\)$;\1;'`
1334            dst="$dst/$dstfile"
1335        fi
1336
1337        #   check for correct arguments
1338        if [ ".$src" = ".$dst" ]; then
1339            echo "$msgprefix:Warning: source and destination are the same - skipped" 1>&2
1340            continue
1341        fi
1342        if [ -d "$src" ]; then
1343            echo "$msgprefix:Warning: source \`$src' is a directory - skipped" 1>&2
1344            continue
1345        fi
1346
1347        #   make a temp file name in the destination directory
1348        dsttmp=`echo $dst |\
1349                sed -e 's;[^/]*$;;' -e 's;\(.\)/$;\1;' -e 's;^$;.;' \
1350                    -e "s;\$;/#INST@$$#;"`
1351
1352        #   verbosity
1353        if [ ".$opt_v" = .yes ]; then
1354            echo "$src -> $dst" 1>&2
1355        fi
1356
1357        #   copy or move the file name to the temp name
1358        #   (because we might be not allowed to change the source)
1359        if [ ".$opt_C" = .yes ]; then
1360            opt_c=yes
1361        fi
1362        if [ ".$opt_c" = .yes ]; then
1363            if [ ".$opt_t" = .yes ]; then
1364                echo "cp $src $dsttmp" 1>&2
1365            fi
1366            cp $src $dsttmp || shtool_exit $?
1367        else
1368            if [ ".$opt_t" = .yes ]; then
1369                echo "mv $src $dsttmp" 1>&2
1370            fi
1371            mv $src $dsttmp || shtool_exit $?
1372        fi
1373
1374        #   adjust the target file
1375        if [ ".$opt_e" != . ]; then
1376            sed='sed'
1377            OIFS="$IFS"; IFS="$ASC_NL"; set -- $opt_e; IFS="$OIFS"
1378            for e
1379            do
1380                sed="$sed -e '$e'"
1381            done
1382            cp $dsttmp $dsttmp.old
1383            chmod u+w $dsttmp
1384            eval "$sed <$dsttmp.old >$dsttmp" || shtool_exit $?
1385            rm -f $dsttmp.old
1386        fi
1387        if [ ".$opt_s" = .yes ]; then
1388            if [ ".$opt_t" = .yes ]; then
1389                echo "strip $dsttmp" 1>&2
1390            fi
1391            strip $dsttmp || shtool_exit $?
1392        fi
1393        if [ ".$opt_o" != . ]; then
1394            if [ ".$opt_t" = .yes ]; then
1395                echo "chown $opt_o $dsttmp" 1>&2
1396            fi
1397            chown $opt_o $dsttmp || shtool_exit $?
1398        fi
1399        if [ ".$opt_g" != . ]; then
1400            if [ ".$opt_t" = .yes ]; then
1401                echo "chgrp $opt_g $dsttmp" 1>&2
1402            fi
1403            chgrp $opt_g $dsttmp || shtool_exit $?
1404        fi
1405        if [ ".$opt_m" != ".-" ]; then
1406            if [ ".$opt_t" = .yes ]; then
1407                echo "chmod $opt_m $dsttmp" 1>&2
1408            fi
1409            chmod $opt_m $dsttmp || shtool_exit $?
1410        fi
1411
1412        #   determine whether to do a quick install
1413        #   (has to be done _after_ the strip was already done)
1414        quick=no
1415        if [ ".$opt_C" = .yes ]; then
1416            if [ -r $dst ]; then
1417                if cmp -s $src $dst; then
1418                    quick=yes
1419                fi
1420            fi
1421        fi
1422
1423        #   finally, install the file to the real destination
1424        if [ $quick = yes ]; then
1425            if [ ".$opt_t" = .yes ]; then
1426                echo "rm -f $dsttmp" 1>&2
1427            fi
1428            rm -f $dsttmp
1429        else
1430            if [ ".$opt_t" = .yes ]; then
1431                echo "rm -f $dst && mv $dsttmp $dst" 1>&2
1432            fi
1433            rm -f $dst && mv $dsttmp $dst
1434        fi
1435    done
1436
1437    shtool_exit 0
1438    ;;
1439
1440mkdir )
1441    ##
1442    ##  mkdir -- Make one or more directories
1443    ##  Copyright (c) 1996-2006 Ralf S. Engelschall <rse@engelschall.com>
1444    ##
1445
1446    errstatus=0
1447    for p in ${1+"$@"}; do
1448        #   if the directory already exists...
1449        if [ -d "$p" ]; then
1450            if [ ".$opt_f" = .no ] && [ ".$opt_p" = .no ]; then
1451                echo "$msgprefix:Error: directory already exists: $p" 1>&2
1452                errstatus=1
1453                break
1454            else
1455                continue
1456            fi
1457        fi
1458        #   if the directory has to be created...
1459        if [ ".$opt_p" = .no ]; then
1460            if [ ".$opt_t" = .yes ]; then
1461                echo "mkdir $p" 1>&2
1462            fi
1463            mkdir $p || errstatus=$?
1464            if [ ".$opt_o" != . ]; then
1465                if [ ".$opt_t" = .yes ]; then
1466                    echo "chown $opt_o $p" 1>&2
1467                fi
1468                chown $opt_o $p || errstatus=$?
1469            fi
1470            if [ ".$opt_g" != . ]; then
1471                if [ ".$opt_t" = .yes ]; then
1472                    echo "chgrp $opt_g $p" 1>&2
1473                fi
1474                chgrp $opt_g $p || errstatus=$?
1475            fi
1476            if [ ".$opt_m" != . ]; then
1477                if [ ".$opt_t" = .yes ]; then
1478                    echo "chmod $opt_m $p" 1>&2
1479                fi
1480                chmod $opt_m $p || errstatus=$?
1481            fi
1482        else
1483            #   the smart situation
1484            set fnord `echo ":$p" |\
1485                       sed -e 's/^:\//%/' \
1486                           -e 's/^://' \
1487                           -e 's/\// /g' \
1488                           -e 's/^%/\//'`
1489            shift
1490            pathcomp=''
1491            for d in ${1+"$@"}; do
1492                pathcomp="$pathcomp$d"
1493                case "$pathcomp" in
1494                    -* ) pathcomp="./$pathcomp" ;;
1495                esac
1496                if [ ! -d "$pathcomp" ]; then
1497                    if [ ".$opt_t" = .yes ]; then
1498                        echo "mkdir $pathcomp" 1>&2
1499                    fi
1500                    mkdir $pathcomp || errstatus=$?
1501                    if [ ".$opt_o" != . ]; then
1502                        if [ ".$opt_t" = .yes ]; then
1503                            echo "chown $opt_o $pathcomp" 1>&2
1504                        fi
1505                        chown $opt_o $pathcomp || errstatus=$?
1506                    fi
1507                    if [ ".$opt_g" != . ]; then
1508                        if [ ".$opt_t" = .yes ]; then
1509                            echo "chgrp $opt_g $pathcomp" 1>&2
1510                        fi
1511                        chgrp $opt_g $pathcomp || errstatus=$?
1512                    fi
1513                    if [ ".$opt_m" != . ]; then
1514                        if [ ".$opt_t" = .yes ]; then
1515                            echo "chmod $opt_m $pathcomp" 1>&2
1516                        fi
1517                        chmod $opt_m $pathcomp || errstatus=$?
1518                    fi
1519                fi
1520                pathcomp="$pathcomp/"
1521            done
1522        fi
1523    done
1524
1525    shtool_exit $errstatus
1526    ;;
1527
1528mkln )
1529    ##
1530    ##  mkln -- Make link with calculation of relative paths
1531    ##  Copyright (c) 1998-2006 Ralf S. Engelschall <rse@engelschall.com>
1532    ##
1533
1534    #   determine source(s) and destination
1535    args=$?
1536    srcs=""
1537    while [ $# -gt 1 ]; do
1538        srcs="$srcs $1"
1539        shift
1540    done
1541    dst="$1"
1542    if [ ! -d $dst ]; then
1543        if [ $args -gt 2 ]; then
1544            echo "$msgprefix:Error: multiple sources not allowed when target isn't a directory" 1>&2
1545            shtool_exit 1
1546        fi
1547    fi
1548
1549    #   determine link options
1550    lnopt=""
1551    if [ ".$opt_f" = .yes ]; then
1552        lnopt="$lnopt -f"
1553    fi
1554    if [ ".$opt_s" = .yes ]; then
1555        lnopt="$lnopt -s"
1556    fi
1557
1558    #   iterate over sources
1559    for src in $srcs; do
1560        #   determine if one of the paths is an absolute path,
1561        #   because then we _have_ to use an absolute symlink
1562        oneisabs=0
1563        srcisabs=0
1564        dstisabs=0
1565        case $src in
1566            /* ) oneisabs=1; srcisabs=1 ;;
1567        esac
1568        case $dst in
1569            /* ) oneisabs=1; dstisabs=1 ;;
1570        esac
1571
1572        #   split source and destination into dir and base name
1573        if [ -d $src ]; then
1574            srcdir=`echo $src | sed -e 's;/*$;;'`
1575            srcbase=""
1576        else
1577            srcdir=`echo  $src | sed -e 's;^[^/]*$;;' -e 's;^\(.*/\)[^/]*$;\1;' -e 's;\(.\)/$;\1;'`
1578            srcbase=`echo $src | sed -e 's;.*/\([^/]*\)$;\1;'`
1579        fi
1580        if [ -d $dst ]; then
1581            dstdir=`echo $dst | sed -e 's;/*$;;'`
1582            dstbase=""
1583        else
1584            dstdir=`echo  $dst | sed -e 's;^[^/]*$;;' -e 's;^\(.*/\)[^/]*$;\1;' -e 's;\(.\)/$;\1;'`
1585            dstbase=`echo $dst | sed -e 's;.*/\([^/]*\)$;\1;'`
1586        fi
1587
1588        #   consistency check
1589        if [ ".$dstdir" != . ]; then
1590            if [ ! -d $dstdir ]; then
1591                echo "$msgprefix:Error: destination directory not found: $dstdir" 1>&2
1592                shtool_exit 1
1593            fi
1594        fi
1595
1596        #   make sure the source is reachable from the destination
1597        if [ $dstisabs = 1 ]; then
1598            if [ $srcisabs = 0 ]; then
1599                if [ ".$srcdir" = . ]; then
1600                    srcdir="`pwd | sed -e 's;/*$;;'`"
1601                    srcisabs=1
1602                    oneisabs=1
1603                elif [ -d $srcdir ]; then
1604                    srcdir="`cd $srcdir; pwd | sed -e 's;/*$;;'`"
1605                    srcisabs=1
1606                    oneisabs=1
1607                fi
1608            fi
1609        fi
1610
1611        #   split away a common prefix
1612        prefix=""
1613        if [ ".$srcdir" = ".$dstdir" ] && [ ".$srcdir" != . ]; then
1614            prefix="$srcdir/"
1615            srcdir=""
1616            dstdir=""
1617        else
1618            while [ ".$srcdir" != . ] && [ ".$dstdir" != . ]; do
1619                presrc=`echo $srcdir | sed -e 's;^\([^/]*\)/.*;\1;'`
1620                predst=`echo $dstdir | sed -e 's;^\([^/]*\)/.*;\1;'`
1621                if [ ".$presrc" != ".$predst" ]; then
1622                    break
1623                fi
1624                prefix="$prefix$presrc/"
1625                srcdir=`echo $srcdir | sed -e 's;^[^/]*/*;;'`
1626                dstdir=`echo $dstdir | sed -e 's;^[^/]*/*;;'`
1627            done
1628        fi
1629
1630        #   destination prefix is just the common prefix
1631        dstpre="$prefix"
1632
1633        #   determine source prefix which is the reverse directory
1634        #   step-up corresponding to the destination directory
1635        srcpre=""
1636
1637        isroot=0
1638        if [ ".$prefix" = . ] || [ ".$prefix" = ./ ]; then
1639            isroot=1
1640        fi
1641        if [ $oneisabs = 0 ] || [ $isroot = 0 ]; then
1642            pl="$dstdir/"
1643            OIFS="$IFS"; IFS='/'
1644            for pe in $pl; do
1645                [ ".$pe" = .  ] && continue
1646                [ ".$pe" = .. ] && continue
1647                srcpre="../$srcpre"
1648            done
1649            IFS="$OIFS"
1650        else
1651            if [ $srcisabs = 1 ]; then
1652                srcpre="$prefix"
1653            fi
1654        fi
1655
1656        #   determine destination symlink name
1657        if [ ".$dstbase" = . ]; then
1658            if [ ".$srcbase" != . ]; then
1659                dstbase="$srcbase"
1660            else
1661                dstbase=`echo "$prefix$srcdir" | sed -e 's;/*$;;' -e 's;.*/\([^/]*\)$;\1;'`
1662            fi
1663        fi
1664
1665        #   now finalize source and destination directory paths
1666        srcdir=`echo $srcdir | sed -e 's;\([^/]\)$;\1/;'`
1667        dstdir=`echo $dstdir | sed -e 's;\([^/]\)$;\1/;'`
1668
1669        #   run the final link command
1670        if [ ".$opt_t" = .yes ]; then
1671            echo "ln$lnopt $srcpre$srcdir$srcbase $dstpre$dstdir$dstbase"
1672        fi
1673        eval ln$lnopt $srcpre$srcdir$srcbase $dstpre$dstdir$dstbase
1674    done
1675
1676    shtool_exit 0
1677    ;;
1678
1679mkshadow )
1680    ##
1681    ##  mkshadow -- Make a shadow tree through symbolic links
1682    ##  Copyright (c) 1998-2006 Ralf S. Engelschall <rse@engelschall.com>
1683    ##
1684
1685    #   source and destination directory
1686    src=`echo "$1" | sed -e 's:/$::' -e 's:^\./\(.\):\1:'`
1687    dst=`echo "$2" | sed -e 's:/$::' -e 's:^\./\(.\):\1:'`
1688
1689    #   check whether source exists
1690    if [ ! -d $src ]; then
1691        echo "$msgprefix:Error: source directory not found: \`$src'" 1>&2
1692        shtool_exit 1
1693    fi
1694
1695    #   determine if one of the paths is an absolute path,
1696    #   because then we have to use an absolute symlink
1697    oneisabs=0
1698    case $src in
1699        /* ) oneisabs=1 ;;
1700    esac
1701    case $dst in
1702        /* ) oneisabs=1 ;;
1703    esac
1704
1705    #   determine reverse directory for destination directory
1706    dstrevdir=''
1707    if [ $oneisabs = 0 ]; then
1708        #   derive reverse path from forward path
1709        pwd=`pwd`
1710        OIFS="$IFS"; IFS='/'
1711        for pe in $dst; do
1712            if [ "x$pe" = "x.." ]; then
1713                OIFS2="$IFS"; IFS="$DIFS"
1714                eval `echo "$pwd" |\
1715                      sed -e 's:\([^/]*\)$:; dir="\1":' \
1716                          -e 's:^\(.*\)/[^/]*;:pwd="\1";:'\
1717                          -e 's:^;:pwd="";:'`
1718                dstrevdir="$dir/$dstrevdir"
1719                IFS="$OIFS2"
1720            else
1721                dstrevdir="../$dstrevdir"
1722            fi
1723        done
1724        IFS="$OIFS"
1725    else
1726        src="`cd $src; pwd`";
1727    fi
1728
1729    #   create directory tree at destination
1730    if [ ! -d $dst ]; then
1731        if [ ".$opt_t" = .yes ]; then
1732            echo "mkdir $dst" 1>&2
1733        fi
1734        mkdir $dst
1735    fi
1736    if [ ".$opt_a" = .yes ]; then
1737        DIRS=`cd $src; find . -type d -print |\
1738              sed -e '/^\.$/d' -e 's:^\./::'`
1739    else
1740        DIRS=`cd $src; find . -type d -print |\
1741              sed -e '/\/CVS/d' -e '/^\.$/d' -e 's:^\./::'`
1742    fi
1743    for dir in $DIRS; do
1744        if [ ".$opt_t" = .yes ]; then
1745            echo "mkdir $dst/$dir" 1>&2
1746        fi
1747        mkdir $dst/$dir
1748    done
1749
1750    #   fill directory tree with symlinks to files
1751    if [ ".$opt_a" = .yes ]; then
1752        FILES="`cd $src; find . -depth -print |\
1753                sed -e 's/^\.\///'`"
1754    else
1755        FILES="`cd $src; find . -depth -print |\
1756                sed -e '/\.o$/d' -e '/\.a$/d' -e '/\.so$/d' \
1757                    -e '/\.cvsignore$/d' -e '/\/CVS/d' \
1758                    -e '/\/\.#/d' -e '/\.orig$/d' \
1759                    -e 's/^\.\///'`"
1760    fi
1761    for file in $FILES; do
1762         #  don't use `-type f' above for find because of symlinks
1763         if [ -d "$src/$file" ]; then
1764             continue
1765         fi
1766         basename=`echo $file | sed -e 's:^.*/::'`
1767         dir=`echo $file | sed -e 's:[^/]*$::' -e 's:/$::' -e 's:$:/:' -e 's:^/$::'`
1768         from=`echo "$src/$file" | sed -e 's/^\.\///'`
1769         to="$dst/$dir$basename"
1770         if [ $oneisabs = 0 ]; then
1771             if [ ".$dir" != . ]; then
1772                 subdir=`echo $dir | sed -e 's:/$::'`
1773                 #   derive reverse path from forward path
1774                 revdir=''
1775                 OIFS="$IFS"; IFS='/'
1776                 for pe in $subdir; do
1777                     revdir="../$revdir"
1778                 done
1779                 IFS="$OIFS"
1780                 #   finalize from
1781                 from="$revdir$from"
1782             fi
1783             from="$dstrevdir$from"
1784         fi
1785         if [ ".$opt_v" = .yes ]; then
1786             echo "    $to" 1>&2
1787         fi
1788         if [ ".$opt_t" = .yes ]; then
1789             echo "ln -s $from $to" 1>&2
1790         fi
1791         ln -s $from $to
1792    done
1793
1794    shtool_exit 0
1795    ;;
1796
1797fixperm )
1798    ##
1799    ##  fixperm -- Fix file permissions inside a source tree
1800    ##  Copyright (c) 1996-2006 Ralf S. Engelschall <rse@engelschall.com>
1801    ##
1802
1803    paths="$*"
1804
1805    #   check whether the test command supports the -x option
1806    if [ -x /bin/sh ] 2>/dev/null; then
1807        minusx="-x"
1808    else
1809        minusx="-r"
1810    fi
1811
1812    #   iterate over paths
1813    for p in $paths; do
1814        for file in `find $p -depth -print`; do
1815            if [ -f $file ]; then
1816                if [ $minusx $file ]; then
1817                    if [ ".$opt_v" = .yes ]; then
1818                        echo "-rwxr-xr-x $file" 2>&1
1819                    fi
1820                    if [ ".$opt_t" = .yes ]; then
1821                        echo "chmod 755 $file" 2>&1
1822                    fi
1823                    chmod 755 $file
1824                else
1825                    if [ ".$opt_v" = .yes ]; then
1826                        echo "-rw-r--r-- $file" 2>&1
1827                    fi
1828                    if [ ".$opt_t" = .yes ]; then
1829                        echo "chmod 644 $file" 2>&1
1830                    fi
1831                    chmod 644 $file
1832                fi
1833                continue
1834            fi
1835            if [ -d $file ]; then
1836                if [ ".$opt_v" = .yes ]; then
1837                    echo "drwxr-xr-x $file" 2>&1
1838                fi
1839                if [ ".$opt_t" = .yes ]; then
1840                    echo "chmod 755 $file" 2>&1
1841                fi
1842                chmod 755 $file
1843                continue
1844            fi
1845            if [ ".$opt_v" = .yes ]; then
1846                echo "?????????? $file" 2>&1
1847            fi
1848        done
1849    done
1850
1851    shtool_exit 0
1852    ;;
1853
1854rotate )
1855    ##
1856    ##  rotate -- Logfile rotation
1857    ##  Copyright (c) 2001-2006 Ralf S. Engelschall <rse@engelschall.com>
1858    ##
1859
1860    #   make sure we have at least one file to rotate
1861    if [ ".$opt_n" = .0 ]; then
1862        echo "$msgprefix:Error: invalid argument \`$opt_n' to option -n." 1>&2
1863        shtool_exit 1
1864    fi
1865
1866    #   canonicalize -s option argument
1867    if [ ".$opt_s" != . ]; then
1868        if [ ".`expr $opt_s : '[0-9]*$'`" != .0 ]; then
1869            :
1870        elif [ ".`expr $opt_s : '[0-9]*[Kk]$'`" != .0 ]; then
1871            opt_s=`expr $opt_s : '\([0-9]*\)[Kk]$'`
1872            opt_s=`expr $opt_s \* 1024`
1873        elif [ ".`expr $opt_s : '[0-9]*[Mm]$'`" != .0 ]; then
1874            opt_s=`expr $opt_s : '\([0-9]*\)[Mm]$'`
1875            opt_s=`expr $opt_s \* 1048576` # 1024*1024
1876        elif [ ".`expr $opt_s : '[0-9]*[Gg]$'`" != .0 ]; then
1877            opt_s=`expr $opt_s : '\([0-9]*\)[Gg]$'`
1878            opt_s=`expr $opt_s \* 1073741824` # 1024*1024*1024
1879        else
1880            echo "$msgprefix:Error: invalid argument \`$opt_s' to option -s." 1>&2
1881            shtool_exit 1
1882        fi
1883    fi
1884
1885    #   option -d/-z consistency
1886    if [ ".$opt_d" = .yes ] && [ ".$opt_z" = . ]; then
1887        echo "$msgprefix:Error: option -d requires option -z." 1>&2
1888        shtool_exit 1
1889    fi
1890
1891    #   make sure target directory exists
1892    if [ ".$opt_a" != . ]; then
1893        if [ ! -d $opt_a ]; then
1894            if [ ".$opt_f" = .no ]; then
1895                echo "$msgprefix:Error: archive directory \`$opt_a' does not exist." 1>&2
1896                shtool_exit 1
1897            fi
1898            mkdir $opt_a || shtool_exit $?
1899            chmod 755 $opt_a
1900        fi
1901        if [ ! -w $opt_a ]; then
1902            echo "$msgprefix:Error: archive directory \`$opt_a' not writable." 1>&2
1903            shtool_exit 1
1904        fi
1905    fi
1906
1907    #   determine compression approach
1908    if [ ".$opt_z" != . ]; then
1909        comp_lvl="$opt_z"
1910        comp_prg=""
1911        case $comp_lvl in
1912            *:* ) eval `echo $comp_lvl |\
1913                        sed -e 's%^\(.*\):\(.*\)$%comp_prg="\1"; comp_lvl="\2"%'` ;;
1914        esac
1915
1916        #   compression level consistency
1917        case $comp_lvl in
1918            [0-9] )
1919                ;;
1920            * ) echo "$msgprefix:Error: invalid compression level \`$comp_lvl'" 1>&2
1921                shtool_exit 1
1922                ;;
1923        esac
1924
1925        #   determine a suitable compression tool
1926        if [ ".$comp_prg" = . ]; then
1927            #   check whether the test command supports the -x option
1928            if [ -x /bin/sh ] 2>/dev/null; then
1929                minusx="-x"
1930            else
1931                minusx="-r"
1932            fi
1933            #   search for tools in $PATH
1934            paths="`echo $PATH |\
1935                    sed -e 's%/*:%:%g' -e 's%/*$%%' \
1936                        -e 's/^:/.:/' -e 's/::/:.:/g' -e 's/:$/:./' \
1937                        -e 's/:/ /g'`"
1938            for prg in bzip2 gzip compress; do
1939                for path in $paths; do
1940                    if [ $minusx "$path/$prg" ] && [ ! -d "$path/$prg" ]; then
1941                        comp_prg="$prg"
1942                        break
1943                    fi
1944                done
1945                if [ ".$comp_prg" != . ]; then
1946                    break
1947                fi
1948            done
1949            if [ ".$comp_prg" = . ]; then
1950                echo "$msgprefix:Error: no suitable compression tool found in \$PATH" 1>&2
1951                shtool_exit 1
1952            fi
1953        fi
1954
1955        #   determine standard compression extension
1956        #   and make sure it is a known tool
1957        case $comp_prg in
1958            */bzip2    | bzip2    ) comp_ext="bz2" comp_lvl="-$comp_lvl" ;;
1959            */gzip     | gzip     ) comp_ext="gz"  comp_lvl="-$comp_lvl" ;;
1960            */compress | compress ) comp_ext="Z";  comp_lvl=""           ;;
1961            * ) echo "$msgprefix:Error: tool \`$comp_prg' is not a known compression tool" 1>&2
1962                shtool_exit 1
1963                ;;
1964        esac
1965        comp_suf=".$comp_ext"
1966    fi
1967
1968    #   iterate over all given logfile arguments
1969    for file in $*; do
1970        #   make sure the logfile exists
1971        if [ ! -f $file ]; then
1972            if [ ".$opt_f" = .yes ]; then
1973                continue
1974            fi
1975            echo "$msgprefix:Error: logfile \`$file' not found" 1>&2
1976            shtool_exit 1
1977        fi
1978
1979        #   determine log directory (where original logfile is placed)
1980        ldir="."
1981        case $file in
1982            */* ) eval `echo $file | sed -e 's%^\(.*\)/\([^/]*\)$%ldir="\1"; file="\2";%'` ;;
1983        esac
1984
1985        #   determine archive directory (where rotated logfiles are placed)
1986        adir="$ldir"
1987        if [ ".$opt_a" != . ]; then
1988            case "$opt_a" in
1989                /* | ./* ) adir="$opt_a" ;;
1990                * ) adir="$ldir/$opt_a"  ;;
1991            esac
1992        fi
1993
1994        #   optionally take logfile size into account
1995        if [ ".$opt_s" != . ]; then
1996            #   determine size of logfile
1997            set -- `env -i /bin/ls -l "$ldir/$file" | sed -e "s;$ldir/$file;;" |\
1998                    sed -e 's; -> .*$;;' -e 's;[ 	][ 	]*; ;g'`
1999            n=`expr $# - 3`
2000            eval "size=\`echo \${$n}\`"
2001
2002            #   skip logfile if size is still too small
2003            if [ $size -lt $opt_s ]; then
2004                if [ ".$opt_v" = .yes ]; then
2005                    echo "$ldir/$file: still too small in size -- skipping"
2006                fi
2007                continue
2008            fi
2009        fi
2010
2011        #   verbosity
2012        if [ ".$opt_v" = .yes ]; then
2013            echo "rotating $ldir/$file"
2014        fi
2015
2016        #   execute prolog
2017        if [ ".$opt_P" != . ]; then
2018            if [ ".$opt_t" = .yes ]; then
2019                echo "$opt_P"
2020            fi
2021            eval $opt_P
2022            [ $? -ne 0 ] && shtool_exit $?
2023        fi
2024
2025        #   kick away out-rotated logfile
2026        n=`expr $opt_n - 1`
2027        n=`echo dummy | awk "{ printf(\"%0${opt_p}d\", n); }" n=$n`
2028        if [ -f "${adir}/${file}.${n}${comp_suf}" ]; then
2029            #   optionally migrate away the out-rotated logfile
2030            if [ ".$opt_M" != . ]; then
2031                if [ ".$opt_t" = .yes ]; then
2032                    echo "$opt_M ${adir}/${file}.${n}${comp_suf}"
2033                fi
2034                eval "$opt_M ${adir}/${file}.${n}${comp_suf}"
2035                [ $? -ne 0 ] && shtool_exit $?
2036            fi
2037            #   finally get rid of the out-rotated logfile
2038            if [ ".$opt_t" = .yes ]; then
2039                echo "rm -f ${adir}/${file}.${n}${comp_suf}"
2040            fi
2041            rm -f ${adir}/${file}.${n}${comp_suf} || shtool_exit $?
2042        fi
2043
2044        #   rotate already archived logfiles
2045        while [ $n -gt 0 ]; do
2046            m=$n
2047            n=`expr $n - 1`
2048            n=`echo dummy | awk "{ printf(\"%0${opt_p}d\", n); }" n=$n`
2049            if [ $n -eq 0 ] && [ ".$opt_d" = .yes ]; then
2050                #   special case: first rotation file under delayed compression situation
2051                if [ ! -f "${adir}/${file}.${n}" ]; then
2052                    continue
2053                fi
2054
2055                #   compress file (delayed)
2056                if [ ".$opt_b" = .yes ]; then
2057                    if [ ".$opt_t" = .yes ]; then
2058                        echo "mv ${adir}/${file}.${n} ${adir}/${file}.${m}"
2059                    fi
2060                    mv ${adir}/${file}.${n} ${adir}/${file}.${m} || shtool_exit $?
2061                    if [ ".$opt_t" = .yes ]; then
2062                        echo "(${comp_prg} ${comp_lvl} <${adir}/${file}.${m} >${adir}/${file}.${m}${comp_suf}; rm -f ${adir}/${file}.${m}) &"
2063                    fi
2064                    ( ${comp_prg} ${comp_lvl} \
2065                          <${adir}/${file}.${m} \
2066                          >${adir}/${file}.${m}${comp_suf} || shtool_exit $?
2067                      rm -f ${adir}/${file}.${m} || shtool_exit $?
2068                    ) </dev/null >/dev/null 2>&1 &
2069                else
2070                    if [ ".$opt_t" = .yes ]; then
2071                        echo "${comp_prg} ${comp_lvl} <${adir}/${file}.${n} >${adir}/${file}.${m}${comp_suf}"
2072                    fi
2073                    ${comp_prg} ${comp_lvl} \
2074                        <${adir}/${file}.${n} \
2075                        >${adir}/${file}.${m}${comp_suf} || shtool_exit $?
2076                    if [ ".$opt_t" = .yes ]; then
2077                        echo "rm -f ${adir}/${file}.${n}"
2078                    fi
2079                    rm -f ${adir}/${file}.${n} || shtool_exit $?
2080                fi
2081
2082                #   fix file attributes
2083                if [ ".$opt_o" != . ]; then
2084                    if [ ".$opt_t" = .yes ]; then
2085                        echo "chown $opt_o ${adir}/${file}.${m}${comp_suf}"
2086                    fi
2087                    chown $opt_o ${adir}/${file}.${m}${comp_suf} || shtool_exit $?
2088                fi
2089                if [ ".$opt_g" != . ]; then
2090                    if [ ".$opt_t" = .yes ]; then
2091                        echo "chgrp $opt_g ${adir}/${file}.${m}${comp_suf}"
2092                    fi
2093                    chgrp $opt_g ${adir}/${file}.${m}${comp_suf} || shtool_exit $?
2094                fi
2095                if [ ".$opt_m" != . ]; then
2096                    if [ ".$opt_t" = .yes ]; then
2097                        echo "chmod $opt_m ${adir}/${file}.${m}${comp_suf}"
2098                    fi
2099                    chmod $opt_m ${adir}/${file}.${m}${comp_suf} || shtool_exit $?
2100                fi
2101            else
2102                #   standard case: second and following rotation file
2103                if [ ! -f "${adir}/${file}.${n}${comp_suf}" ]; then
2104                    continue
2105                fi
2106                if [ ".$opt_t" = .yes ]; then
2107                    echo "mv ${adir}/${file}.${n}${comp_suf} ${adir}/${file}.${m}${comp_suf}"
2108                fi
2109                mv ${adir}/${file}.${n}${comp_suf} ${adir}/${file}.${m}${comp_suf} || shtool_exit $?
2110            fi
2111        done
2112
2113        #   move away current logfile
2114        if [ ".$opt_c" = .yes ]; then
2115            #   approach: copy[+truncate]
2116            if [ ".$opt_t" = .yes ]; then
2117                echo "cp -p ${ldir}/${file} ${adir}/${file}.${n}"
2118            fi
2119            cp -p ${ldir}/${file} ${adir}/${file}.${n} || shtool_exit $?
2120            if [ ".$opt_r" = .no ]; then
2121                if [ ".$opt_t" = .yes ]; then
2122                    echo "cp /dev/null ${ldir}/${file}"
2123                fi
2124                cp /dev/null ${ldir}/${file} || shtool_exit $?
2125            fi
2126        else
2127            #   approach: move[+touch]
2128            if [ ".$opt_t" = .yes ]; then
2129                echo "mv ${ldir}/${file} ${adir}/${file}.${n}"
2130            fi
2131            mv ${ldir}/${file} ${adir}/${file}.${n} || shtool_exit $?
2132            if [ ".$opt_r" = .no ]; then
2133                if [ ".$opt_t" = .yes ]; then
2134                    echo "touch ${ldir}/${file}"
2135                fi
2136                touch ${ldir}/${file} || shtool_exit $?
2137                #   fix file attributes
2138                if [ ".$opt_o" != . ]; then
2139                    if [ ".$opt_t" = .yes ]; then
2140                        echo "chown $opt_o ${ldir}/${file}"
2141                    fi
2142                    chown $opt_o ${ldir}/${file} || shtool_exit $?
2143                fi
2144                if [ ".$opt_g" != . ]; then
2145                    if [ ".$opt_t" = .yes ]; then
2146                        echo "chgrp $opt_g ${ldir}/${file}"
2147                    fi
2148                    chgrp $opt_g ${ldir}/${file} || shtool_exit $?
2149                fi
2150                if [ ".$opt_m" != . ]; then
2151                    if [ ".$opt_t" = .yes ]; then
2152                        echo "chmod $opt_m ${ldir}/${file}"
2153                    fi
2154                    chmod $opt_m ${ldir}/${file} || shtool_exit $?
2155                fi
2156            fi
2157        fi
2158
2159        #   regular compression step
2160        if [ ".$opt_z" != . ] && [ ".$opt_d" = .no ]; then
2161            #   compress file
2162            if [ ".$opt_b" = .yes ]; then
2163                if [ ".$opt_t" = .yes ]; then
2164                    echo "(${comp_prg} ${comp_lvl} <${adir}/${file}.${n} >${adir}/${file}.${n}${comp_suf}; rm -f ${adir}/${file}.${n}) &"
2165                fi
2166                ( ${comp_prg} ${comp_lvl} \
2167                      <${adir}/${file}.${n} \
2168                      >${adir}/${file}.${n}${comp_suf} || shtool_exit $?
2169                  rm -f ${adir}/${file}.${n} || shtool_exit $?
2170                ) </dev/null >/dev/null 2>&1 &
2171            else
2172                if [ ".$opt_t" = .yes ]; then
2173                    echo "${comp_prg} ${comp_lvl} <${adir}/${file}.${n} >${adir}/${file}.${n}${comp_suf}"
2174                fi
2175                ${comp_prg} ${comp_lvl} \
2176                    <${adir}/${file}.${n} \
2177                    >${adir}/${file}.${n}${comp_suf} || shtool_exit $?
2178                if [ ".$opt_t" = .yes ]; then
2179                    echo "rm -f ${opt_a}${file}.${n}"
2180                fi
2181                rm -f ${adir}/${file}.${n} || shtool_exit $?
2182            fi
2183
2184            #   fix file attributes
2185            if [ ".$opt_o" != . ]; then
2186                if [ ".$opt_t" = .yes ]; then
2187                    echo "chown $opt_o ${adir}/${file}.${n}${comp_suf}"
2188                fi
2189                chown $opt_o ${adir}/${file}.${n}${comp_suf} || shtool_exit $?
2190            fi
2191            if [ ".$opt_g" != . ]; then
2192                if [ ".$opt_t" = .yes ]; then
2193                    echo "chgrp $opt_g ${adir}/${file}.${n}${comp_suf}"
2194                fi
2195                chgrp $opt_g ${adir}/${file}.${n}${comp_suf} || shtool_exit $?
2196            fi
2197            if [ ".$opt_m" != . ]; then
2198                if [ ".$opt_t" = .yes ]; then
2199                    echo "chmod $opt_m ${adir}/${file}.${n}${comp_suf}"
2200                fi
2201                chmod $opt_m ${adir}/${file}.${n}${comp_suf} || shtool_exit $?
2202            fi
2203        fi
2204
2205        #   execute epilog
2206        if [ ".$opt_E" != . ]; then
2207            if [ ".$opt_t" = .yes ]; then
2208                echo "$opt_E"
2209            fi
2210            eval $opt_E
2211            [ $? -ne 0 ] && shtool_exit $?
2212        fi
2213    done
2214
2215    shtool_exit 0
2216    ;;
2217
2218tarball )
2219    ##
2220    ##  tarball -- Roll distribution tarballs
2221    ##  Copyright (c) 1999-2006 Ralf S. Engelschall <rse@engelschall.com>
2222    ##
2223
2224    srcs="$*"
2225
2226    #   check whether the test command supports the -x option
2227    if [ -x /bin/sh ] 2>/dev/null; then
2228        minusx="-x"
2229    else
2230        minusx="-r"
2231    fi
2232
2233    #   find the tools
2234    paths="`echo $PATH |\
2235            sed -e 's%/*:%:%g' -e 's%/*$%%' \
2236                -e 's/^:/.:/' -e 's/::/:.:/g' -e 's/:$/:./' \
2237                -e 's/:/ /g'`"
2238    for spec in find:gfind,find tar:gtar,tar tardy:tardy,tarcust; do
2239        prg=`echo $spec | sed -e 's/:.*$//'`
2240        tools=`echo $spec | sed -e 's/^.*://'`
2241        eval "prg_${prg}=''"
2242        #   iterate over tools
2243        for tool in `echo $tools | sed -e 's/,/ /g'`; do
2244            #   iterate over paths
2245            for path in $paths; do
2246                if [ $minusx "$path/$tool" ] && [ ! -d "$path/$tool" ]; then
2247                    eval "prg_${prg}=\"$path/$tool\""
2248                    break
2249                fi
2250            done
2251            eval "val=\$prg_${prg}"
2252            if [ ".$val" != . ]; then
2253                break
2254            fi
2255        done
2256    done
2257
2258    #   expand source paths
2259    exclude=''
2260    for pat in `echo $opt_e | sed 's/,/ /g'`; do
2261        exclude="$exclude | grep -v '$pat'"
2262    done
2263    if [ ".$opt_t" = .yes ]; then
2264        echo "cp /dev/null $tmpfile.lst" 1>&2
2265    fi
2266    cp /dev/null $tmpfile.lst
2267    for src in $srcs; do
2268        if [ -d $src ]; then
2269            if [ ".$opt_t" = .yes ]; then
2270                echo "(cd $src && $prg_find . -type f -depth -print) | sed -e 's:^\\.\$::' -e 's:^\\./::' | cat $exclude >>$tmpfile.lst" 1>&2
2271            fi
2272            (cd $src && $prg_find . -type f -depth -print) |\
2273            sed -e 's:^\.$::' -e 's:^\./::' | eval cat $exclude >>$tmpfile.lst
2274        else
2275            if [ ".$opt_t" = .yes ]; then
2276                echo "echo $src >>$tmpfile.lst" 1>&2
2277            fi
2278            echo $src >>$tmpfile.lst
2279        fi
2280    done
2281    sort <$tmpfile.lst >$tmpfile.lst.n
2282    mv $tmpfile.lst.n $tmpfile.lst
2283    if [ ".$opt_v" = .yes ]; then
2284        cat $tmpfile.lst | sed -e 's/^/  /' 1>&2
2285    fi
2286
2287    #   determine tarball file and directory name
2288    if [ ".$opt_o" != . ]; then
2289        tarfile="$opt_o"
2290        if [ ".$opt_d" != . ]; then
2291            tarname="$opt_d"
2292        else
2293            tarname=`echo $tarfile | sed -e 's/\.tar.*$//' -e 's;.*/\([^/]*\)$;\1;'`
2294        fi
2295    else
2296        if [ ".$opt_d" != . ]; then
2297            tarname="$opt_d"
2298        elif [ -d "$from" ]; then
2299            tarname=`echo $from | sed -e 's;.*/\([^/]*\)$;\1;'`
2300        else
2301            tarname="out"
2302        fi
2303        tarfile="$tarname.tar"
2304    fi
2305
2306    #   roll the tarball
2307    compress=''
2308    if [ ".$opt_c" != . ]; then
2309        compress="| $opt_c"
2310    fi
2311    if [ ".$prg_tardy" != . ]; then
2312        #   the elegant hackers way
2313        tardy_opt="--prefix=$tarname"
2314        tardy_opt="$tardy_opt --user_number=0 --group_number=0" # security!
2315        if [ ".$opt_u" != . ]; then
2316            tardy_opt="$tardy_opt --user_name=$opt_u"
2317        fi
2318        if [ ".$opt_g" != . ]; then
2319            tardy_opt="$tardy_opt --group_name=$opt_g"
2320        fi
2321        if [ ".$opt_t" = .yes ]; then
2322            echo "cat $tmpfile.lst | xargs $prg_tar cf - | $prg_tardy $tardy_opt | cat $compress >$tmpfile.out" 1>&2
2323        fi
2324        cat $tmpfile.lst |\
2325        xargs $prg_tar cf - |\
2326        $prg_tardy $tardy_opt |\
2327        eval cat $compress >$tmpfile.out
2328        if [ ".$opt_t" = .yes ]; then
2329            echo "cp $tmpfile.out $tarfile" 1>&2
2330        fi
2331        cp $tmpfile.out $tarfile
2332    else
2333        #  the portable standard way
2334        if [ ".$opt_t" = .yes ]; then
2335            echo "mkdir $tmpdir/$tarname" 1>&2
2336        fi
2337        mkdir $tmpdir/$tarname || shtool_exit 1
2338        if [ ".$opt_t" = .yes ]; then
2339            echo "cat $tmpfile.lst | xargs $prg_tar cf - | (cd $tmpdir/$tarname && $prg_tar xf -)" 1>&2
2340        fi
2341        cat $tmpfile.lst |\
2342        xargs $prg_tar cf - |\
2343        (cd $tmpdir/$tarname && $prg_tar xf -)
2344        if [ ".$opt_u" != . ]; then
2345            if [ ".$opt_t" = .yes ]; then
2346                echo "chown -R $opt_u $tmpdir/$tarname >/dev/null 2>&1" 2>&1
2347            fi
2348            chown -R $opt_u $tmpdir/$tarname >/dev/null 2>&1 ||\
2349            echo "$msgprefix:Warning: cannot set user name \`$opt_u' (would require root privileges)"
2350        fi
2351        if [ ".$opt_g" != . ]; then
2352            if [ ".$opt_t" = .yes ]; then
2353                echo "chgrp -R $opt_g $tmpdir/$tarname >/dev/null 2>&1" 2>&1
2354            fi
2355            chgrp -R $opt_g $tmpdir/$tarname >/dev/null 2>&1 ||\
2356            echo "$msgprefix:Warning: cannot set group name \`$opt_g' (would require root privileges)"
2357        fi
2358        if [ ".$opt_t" = .yes ]; then
2359            echo "(cd $tmpdir && $prg_find $tarname -type f -depth -print | sort | xargs $prg_tar cf -) | cat $compress >$tmpfile.out" 1>&2
2360        fi
2361        (cd $tmpdir && $prg_find $tarname -type f -depth -print | sort | xargs $prg_tar cf -) |\
2362        eval cat $compress >$tmpfile.out
2363        if [ ".$opt_t" = .yes ]; then
2364            echo "cp $tmpfile.out $tarfile" 1>&2
2365        fi
2366        cp $tmpfile.out $tarfile
2367        if [ ".$opt_t" = .yes ]; then
2368            echo "rm -rf $tmpdir/$tarname" 1>&2
2369        fi
2370        rm -rf $tmpdir/$tarname
2371    fi
2372
2373    #   cleanup
2374    if [ ".$opt_t" = .yes ]; then
2375        echo "rm -f $tmpfile.lst $tmpfile.out" 1>&2
2376    fi
2377    rm -f $tmpfile.lst $tmpfile.out
2378
2379    shtool_exit 0
2380    ;;
2381
2382subst )
2383    ##
2384    ##  subst -- Apply sed(1) substitution operations
2385    ##  Copyright (c) 2001-2006 Ralf S. Engelschall <rse@engelschall.com>
2386    ##
2387
2388    #   remember optional list of file(s)
2389    files="$*"
2390    files_num="$#"
2391
2392    #   parameter consistency check
2393    if [ $# -eq 0 ] && [ ".$opt_b" != . ]; then
2394        echo "$msgprefix:Error: option -b cannot be applied to stdin" 1>&2
2395        shtool_exit 1
2396    fi
2397    if [ $# -eq 0 ] && [ ".$opt_s" = .yes ]; then
2398        echo "$msgprefix:Error: option -s cannot be applied to stdin" 1>&2
2399        shtool_exit 1
2400    fi
2401
2402    #   build underlying sed(1) command
2403    sedcmd='sed'
2404    if [ ".$opt_e" != . ]; then
2405        OIFS="$IFS"; IFS="$ASC_NL"; set -- $opt_e; IFS="$OIFS"
2406        for e
2407        do
2408            sedcmd="$sedcmd -e '$e'"
2409        done
2410    elif [ ".$opt_f" != . ]; then
2411        if [ ! -f $opt_f ]; then
2412            echo "$msgprefix:Error: command file \`$opt_f' not found or not a regular file" 1>&2
2413            shtool_exit 1
2414        fi
2415        sedcmd="$sedcmd -f '$opt_f'"
2416    else
2417        echo "$msgprefix:Error: either -e option(s) or -f option required" 1>&2
2418        shtool_exit 1
2419    fi
2420
2421    #   determine extension for original file
2422    orig=".orig"
2423    if [ ".$opt_b" != . ]; then
2424        orig="$opt_b"
2425    fi
2426
2427    #   apply sed(1) operation(s)
2428    if [ ".$files" != . ]; then
2429        #   apply operation(s) to files
2430        substdone=no
2431        for file in $files; do
2432            test ".$file" = . && continue
2433            if [ ! -f $file ]; then
2434                echo "$msgprefix:Warning: file \`$file' not found or not a regular file" 1>&2
2435                continue
2436            fi
2437
2438            #   handle interactive mode
2439            if [ ".$opt_i" = .yes ]; then
2440                eval "$sedcmd <$file >$file.new"
2441                skip=no
2442                if cmp $file $file.new >/dev/null 2>&1; then
2443                    rm -f $file.new
2444                    skip=yes
2445                else
2446                    (diff -U1 $file $file.new >$tmpfile) 2>/dev/null
2447                    if [ ".`cat $tmpfile`" = . ]; then
2448                        (diff -C1 $file $file.new >$tmpfile) 2>/dev/null
2449                        if [ ".`cat $tmpfile`" = . ]; then
2450                            echo "$msgprefix:Warning: unable to show difference for file \`$file'" 1>&2
2451                            cp /dev/null $tmpfile
2452                        fi
2453                    fi
2454                    rm -f $file.new
2455                    cat $tmpfile
2456                    echo dummy | awk '{ printf("%s", TEXT); }' TEXT=">>> Apply [Y/n]: "
2457                    read input
2458                    if [ ".$input" != .Y ] &&\
2459                       [ ".$input" != .y ] &&\
2460                       [ ".$input" != . ]; then
2461                       skip=yes
2462                    fi
2463                fi
2464                if [ ".$skip" = .yes ]; then
2465                    if [ ".$opt_v" = .yes ]; then
2466                        echo "file \`$file' -- skipped" 1>&2
2467                    fi
2468                    continue
2469                fi
2470            fi
2471
2472            #   apply sed(1) operation(s)
2473            if [ ".$opt_v" = .yes ]; then
2474                echo "patching \`$file'" 1>&2
2475            fi
2476            if [ ".$opt_t" = .yes ]; then
2477                echo "\$ cp -p $file $file$orig"
2478                echo "\$ chmod u+w $file"
2479                echo "\$ $sedcmd <$file$orig >$file"
2480            fi
2481            if [ ".$opt_n" = .no ]; then
2482                cp -p $file $file$orig
2483                chmod u+w $file >/dev/null 2>&1 || true
2484                eval "$sedcmd <$file$orig >$file"
2485            fi
2486
2487            #   optionally fix timestamp
2488            if [ ".$opt_s" = .yes ]; then
2489                if [ ".$opt_t" = .yes ]; then
2490                    echo "\$ touch -r $file$orig $file"
2491                fi
2492                if [ ".$opt_n" = .no ]; then
2493                    touch -r $file$orig $file
2494                fi
2495            fi
2496
2497            #   optionally check whether any content change actually occurred
2498            if [ ".$opt_q" = .no ]; then
2499                if cmp $file$orig $file >/dev/null 2>&1; then
2500                    if [ ".$opt_w" = .yes ]; then
2501                        echo "$msgprefix:Warning: substitution resulted in no content change on file \"$file\"" 1>&2
2502                    fi
2503                else
2504                    substdone=yes
2505                fi
2506            fi
2507
2508            #   optionally remove preserved original file
2509            if [ ".$opt_b" = . ]; then
2510                if [ ".$opt_t" = .yes ]; then
2511                    echo "\$ rm -f $file$orig"
2512                fi
2513                if [ ".$opt_n" = .no ]; then
2514                    rm -f $file$orig
2515                fi
2516            fi
2517        done
2518        if [ ".$opt_q" = .no ] && [ ".$opt_w" = .no ]; then
2519            if [ ".$substdone" = .no ]; then
2520                if [ ".$files_num" = .1 ]; then
2521                    echo "$msgprefix:Warning: substitution resulted in no content change on file \"$file\"" 1>&2
2522                else
2523                    echo "$msgprefix:Warning: substitution resulted in no content change on any file" 1>&2
2524                fi
2525            fi
2526        fi
2527    else
2528        #   apply operation(s) to stdin/stdout
2529        if [ ".$opt_v" = .yes ]; then
2530            echo "patching <stdin>" 1>&2
2531        fi
2532        if [ ".$opt_t" = .yes ]; then
2533            echo "\$ $sedcmd"
2534        fi
2535        if [ ".$opt_n" = .no ]; then
2536            eval "$sedcmd"
2537        fi
2538    fi
2539
2540    shtool_exit 0
2541    ;;
2542
2543platform )
2544    ##
2545    ##  platform -- Platform Identification Utility
2546    ##  Copyright (c) 2003-2006 Ralf S. Engelschall <rse@engelschall.com>
2547    ##
2548
2549    #   option post-processing
2550    if [ ".$opt_t" != . ]; then
2551        case "$opt_t" in
2552            binary )
2553                #   binary package id (OpenPKG RPM)
2554                opt_F="%<ap>-%<sp>"
2555                opt_L=yes
2556                opt_S=""
2557                opt_C="+"
2558                ;;
2559            build )
2560                #   build time checking (OpenPKG RPM)
2561                opt_F="%<at>-%<st>"
2562                opt_L=yes
2563                opt_S=""
2564                opt_C="+"
2565                ;;
2566            gnu )
2567                #   GNU config.guess style <arch>-<vendor>-<os><osversion>
2568                opt_F="%<at>-unknown-%<st>"
2569                opt_L=yes
2570                opt_S=""
2571                opt_C="+"
2572                ;;
2573            web )
2574                #   non-whitespace HTTP Server-header id
2575                opt_F="%<sp>-%<ap>"
2576                opt_S="/"
2577                opt_C="+"
2578                ;;
2579            summary)
2580                #   human readable verbose summary information
2581                opt_F="Class:      %[sc] (%[ac])\\nProduct:    %[sp] (%[ap])\\nTechnology: %[st] (%[at])"
2582                opt_S=" "
2583                opt_C="/"
2584                ;;
2585            all-in-one )
2586                #   full-table all-in-one information
2587                opt_F=""
2588                opt_F="${opt_F}concise architecture class:      %<ac>\\n"
2589                opt_F="${opt_F}regular architecture class:      %{ac}\\n"
2590                opt_F="${opt_F}verbose architecture class:      %[ac]\\n"
2591                opt_F="${opt_F}concise architecture product:    %<ap>\\n"
2592                opt_F="${opt_F}regular architecture product:    %{ap}\\n"
2593                opt_F="${opt_F}verbose architecture product:    %[ap]\\n"
2594                opt_F="${opt_F}concise architecture technology: %<at>\\n"
2595                opt_F="${opt_F}regular architecture technology: %{at}\\n"
2596                opt_F="${opt_F}verbose architecture technology: %[at]\\n"
2597                opt_F="${opt_F}concise system class:            %<sc>\\n"
2598                opt_F="${opt_F}regular system class:            %{sc}\\n"
2599                opt_F="${opt_F}verbose system class:            %[sc]\\n"
2600                opt_F="${opt_F}concise system product:          %<sp>\\n"
2601                opt_F="${opt_F}regular system product:          %{sp}\\n"
2602                opt_F="${opt_F}verbose system product:          %[sp]\\n"
2603                opt_F="${opt_F}concise system technology:       %<st>\\n"
2604                opt_F="${opt_F}regular system technology:       %{st}\\n"
2605                opt_F="${opt_F}verbose system technology:       %[st]"
2606                ;;
2607            * )
2608                echo "$msgprefix:Error: invalid type \`$opt_t'" 1>&2
2609                exit 1
2610                ;;
2611        esac
2612    fi
2613
2614    #   assemble initial platform information
2615    UNAME_MACHINE=`(uname -m) 2>/dev/null` ||\
2616    UNAME_MACHINE=`(uname -p) 2>/dev/null` ||\
2617    UNAME_MACHINE='unknown'
2618    UNAME_SYSTEM=`(uname -s) 2>/dev/null`  ||\
2619    UNAME_SYSTEM='unknown'
2620    UNAME_RELEASE=`(uname -r) 2>/dev/null` ||\
2621    UNAME_RELEASE=`(uname -v) 2>/dev/null` ||\
2622    UNAME_RELEASE='unknown'
2623
2624    UNAME="${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}"
2625
2626    AC=""; AP=""; AT=""
2627    SC=""; SP=""; ST=""
2628
2629    #    dispatch into platform specific sections
2630    case "${UNAME}" in
2631
2632        #   FreeBSD
2633        *:FreeBSD:* )
2634            #   determine architecture
2635            AC="${UNAME_MACHINE}"
2636            case "${AC}" in
2637                i386 ) AC="iX86" ;;
2638            esac
2639            AP="${AC}"
2640            AT="${AP}"
2641            if [ ".${AT}" = ".iX86" ]; then
2642                case "`(/sbin/sysctl -n hw.model) 2>&1`" in
2643                    *"Xeon"* | *"Pentium Pro"* | *"Cyrix 6x86MX"* | *"Pentium II"* | *"Pentium III"* | *"Pentium 4"* | *"Celeron"* ) AT="i686" ;;
2644                    *"Pentium"* ) AT="i586" ;; *"i486[SD]X"* | *"Cyrix 486"* | *"Cyrix [56]x86"* | *"Blue Lightning" | *"Cyrix 486S/DX" ) AT="i486" ;;
2645                    *"i386[SD]X"* | *"NexGen 586"* ) AT="i386" ;;
2646                esac
2647            fi
2648            #   determine system
2649            r=`echo "${UNAME_RELEASE}" |\
2650               sed -e 's;[()];;' -e 's/\(-.*\)$/[\1]/'`
2651            ST="FreeBSD ${r}"
2652            SP="${ST}"
2653            case "${r}" in
2654                1.* ) SC="4.3BSD" ;;
2655                *   ) SC="4.4BSD" ;;
2656            esac
2657            ;;
2658
2659        #   NetBSD
2660        *:NetBSD:* )
2661            #   determine architecture
2662            AT="${UNAME_MACHINE}"
2663            AP="${AT}"
2664            case "${AP}" in
2665                i[3-6]86 ) AP="iX86" ;;
2666            esac
2667            AC="${AP}"
2668            #   determine system
2669            r=`echo "${UNAME_RELEASE}" | sed -e 's/\([-_].*\)$/[\1]/'`
2670            ST="NetBSD ${r}"
2671            SP="${ST}"
2672            case "${r}" in
2673                0.* ) SC="4.3BSD" ;;
2674                *   ) SC="4.4BSD" ;;
2675            esac
2676            ;;
2677
2678        #   OpenBSD
2679        *:OpenBSD:* )
2680            #   determine architecture
2681            AT="${UNAME_MACHINE}"
2682            AP="${AT}"
2683            case "${AP}" in
2684                i[3-6]86 ) AP="iX86" ;;
2685            esac
2686            AC="${AP}"
2687            #   determine system
2688            r=`echo "${UNAME_RELEASE}" | sed -e 's/\([-_].*\)$/[\1]/'`
2689            ST="OpenBSD ${r}"
2690            SP="${ST}"
2691            SC="4.4BSD"
2692            ;;
2693
2694        #   GNU/Linux
2695        *:Linux:* )
2696            #   determine architecture
2697            AT="${UNAME_MACHINE}"
2698            case "${AT}" in
2699               ia64     ) AT="IA64"   ;;
2700               x86_64   ) AT='AMD64'  ;;
2701               parisc   ) AT="HPPA32" ;;
2702               parisc64 ) AT="HPPA64" ;;
2703            esac
2704            AP="${AT}"
2705            case "${AP}" in
2706               i[3-6]86 ) AP='iX86' ;;
2707            esac
2708            AC="${AP}"
2709            #   determine system
2710            v_kern=`echo "${UNAME_RELEASE}" |\
2711                sed -e 's/^\([0-9][0-9]*\.[0-9][0-9]*\).*/\1/'`
2712            v_libc=`(strings /lib/libc.so.* | grep '^GLIBC_' | sed -e 's/^GLIBC_//' |\
2713                env -i sort -n | sed -n -e '$p' | sed -e 's/^\([0-9][0-9]*\.[0-9][0-9]*\).*/\1/') 2>/dev/null`
2714            ST="GNU/<Linux >${v_libc}/<${v_kern}>"
2715            if [ -f /etc/lsb-release ]; then
2716                eval `( . /etc/lsb-release
2717                    echo "SC=\"LSB${LSB_VERSION}\""
2718                    if [ ".${DISTRIB_ID}" != . -a ".${DISTRIB_RELEASE}" != . ]; then
2719                        echo "SP=\"${DISTRIB_ID} ${DISTRIB_RELEASE}\""
2720                    fi
2721                ) 2>/dev/null`
2722            fi
2723            if [ ".$SP" = . ]; then
2724                for tagfile in x \
2725                    `cd /etc && \
2726                    /bin/ls *[_-]release *[_-]version 2>/dev/null | env -i sort | \
2727                    sed -e '/^redhat-release$/d' -e '/^lsb-release$/d'; \
2728                    echo redhat-release lsb-release`
2729                do
2730                    [ ".${tagfile}" = .x ] && continue
2731                    [ ! -f "/etc/${tagfile}" ] && continue
2732                    n=`echo ${tagfile} | sed -e 's/[_-]release$//' -e 's/[_-]version$//'`
2733                    v=`(grep VERSION /etc/${tagfile}; cat /etc/${tagfile}) | grep '[0-9]' | sed -e 'q' |\
2734                       sed -e 's/^/#/' \
2735                           -e 's/^#[^0-9]*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*$/\1/' \
2736                           -e 's/^#[^0-9]*\([0-9][0-9]*\.[0-9][0-9]*\).*$/\1/' \
2737                           -e 's/^#[^0-9]*\([0-9][0-9]*\).*$/\1/' \
2738                           -e 's/^#.*$//'`
2739                    case "`util_lower ${n}`" in
2740                        redhat )
2741                            if [ ".`grep 'Red Hat Enterprise Linux' /etc/${tagfile}`" != . ]; then
2742                                n="<R>ed <H>at <E>nterprise <L>inux"
2743                            else
2744                                n="<R>ed <H>at <L>inux"
2745                            fi
2746                            ;;
2747                        debian             ) n="Debian[ GNU/Linux]"        ;;
2748                        ubuntu             ) n="Ubuntu[ GNU/Linux]"        ;;
2749                        fedora             ) n="<Fedora> Core[ GNU/Linux]" ;;
2750                        suse               ) n="SuSE[ Linux]"              ;;
2751                        mandrake*|mandriva ) n="Mandriva[ Linux]"          ;;
2752                        gentoo             ) n="Gentoo[ GNU/Linux]"        ;;
2753                        slackware          ) n="Slackware[ Linux]"         ;;
2754                        turbolinux         ) n="TurboLinux"                ;;
2755                        unitedlinux        ) n="UnitedLinux"               ;;
2756                        *                  ) n="${n}[ GNU/Linux]"          ;;
2757                    esac
2758                    case "$n" in
2759                        *"<"*">"* ) SP="$n <$v>" ;;
2760                        *         ) SP="$n $v"   ;;
2761                    esac
2762                    break
2763                done
2764            fi
2765            [ ".$SP" = . ] && SP="${ST}"
2766            [ ".$SC" = . ] && SC="LSB"
2767            ;;
2768
2769        #   Sun Solaris
2770        *:SunOS:* )
2771            #   determine architecture
2772            AT="${UNAME_MACHINE}"
2773            case "${AT}" in
2774                i86pc )
2775                    AT="iX86"
2776                    case "`(/bin/isainfo -k) 2>&1`" in
2777                        amd64 ) AT="AMD64" ;;
2778                    esac
2779                    ;;
2780            esac
2781            AP="${AT}"
2782            case "${AP}" in
2783                sun4[cdm] ) AP="SPARC32" ;;
2784                sun4[uv]  ) AP="SPARC64" ;;
2785                sun4*     ) AP="SPARC"   ;;
2786            esac
2787            AC="${AP}"
2788            case "${AC}" in
2789                SPARC* ) AC="SPARC" ;;
2790            esac
2791            #   determine system
2792            ST="[Sun ]SunOS ${UNAME_RELEASE}"
2793            v=`echo "${UNAME_RELEASE}" |\
2794               sed -e 's;^4\.;1.;' \
2795                   -e 's;^5\.\([0-6]\)[^0-9]*$;2.\1;' \
2796                   -e 's;^5\.\([0-9][0-9]*\).*;\1;'`
2797            SP="[Sun ]Solaris $v"
2798            case "${UNAME_RELEASE}" in
2799                4.* ) SC="4.3BSD" ;;
2800                5.* ) SC="SVR4"   ;;
2801            esac
2802            ;;
2803
2804        #   SCO UnixWare
2805        *:UnixWare:* )
2806            #   determine architecture
2807            AT="${UNAME_MACHINE}"
2808            case "${AT}" in
2809                i[3-6]86 | ix86at ) AT="iX86" ;;
2810            esac
2811            AP="${AT}"
2812            #   determine system
2813            v=`/sbin/uname -v`
2814            ST="[SCO ]UnixWare ${v}"
2815            SP="${ST}"
2816            SC="SVR${UNAME_RELEASE}"
2817            ;;
2818
2819        #   QNX
2820        *:QNX:* )
2821            #   determine architecture
2822            AT="${UNAME_MACHINE}"
2823            case "${AT}" in
2824                x86pc ) AT="iX86" ;;
2825            esac
2826            AP="${AT}"
2827            #   determine system
2828            v="${UNAME_RELEASE}"
2829            ST="QNX[ Neutrino RTOS] ${v}"
2830            v=`echo "${v}" | sed -e 's;^\([0-9][0-9]*\.[0-9][0-9]*\).*$;\1;'`
2831            SP="QNX[ Neutrino RTOS] ${v}"
2832            SC="QNX"
2833            ;;
2834
2835        #   SGI IRIX
2836        *:IRIX*:* )
2837            #   determine architecture
2838            AT="${UNAME_MACHINE}"
2839            AP="${AT}"
2840            case "${AP}:${UNAME_SYSTEM}" in
2841                IP*:IRIX64 ) AP="MIPS64" ;;
2842                IP*:*      ) AP="MIPS"   ;;
2843            esac
2844            AC="${AP}"
2845            #   determine system
2846            v=`(/bin/uname -R || /bin/uname -r) 2>/dev/null | sed -e 's;[0-9.]* ;;'`
2847            ST="[SGI ]IRIX ${v}"
2848            v="${UNAME_RELEASE}"
2849            SP="[SGI ]IRIX ${v}"
2850            SC="4.2BSD/SVR3"
2851            ;;
2852
2853        #   HP HP-UX
2854        *:HP-UX:* )
2855            #   determine architecture
2856            AT="${UNAME_MACHINE}"
2857            case "${AT}" in
2858                ia64 ) AT="IA64" ;;
2859                9000/[34]?? ) AT=M68K ;;
2860                9000/[678][0-9][0-9])
2861                    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
2862                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
2863                    case "${sc_cpu_version}" in
2864                        523 ) AT="HPPA1.0" ;;
2865                        528 ) AT="HPPA1.1" ;;
2866                        532 ) AT="HPPA2.0"
2867                            case "${sc_kernel_bits}" in
2868                                32 ) AT="${AT}n" ;;
2869                                64 ) AT="${AT}w" ;;
2870                            esac
2871                            ;;
2872                    esac
2873                    ;;
2874            esac
2875            AP="${AT}"
2876            case "${AP}" in
2877                HPPA* ) AP="HPPA" ;;
2878            esac
2879            AC="${AP}"
2880            #   determine system
2881            v=`echo "${UNAME_RELEASE}" | sed -e 's;^[^0-9]*;;'`
2882            ST="[HP ]<HP>-<UX ${v}>"
2883            SP="${ST}"
2884            case "${v}" in
2885                10.*   ) SC="SVR4.2" ;;
2886                [7-9]* ) SC="SVR4"   ;;
2887            esac
2888            ;;
2889
2890        #   HP Tru64 (OSF1)
2891        *:OSF1:* )
2892            #   determine architecture
2893            AP="${UNAME_MACHINE}"
2894            case "${AP}" in
2895                alpha ) AP="Alpha" ;;
2896            esac
2897            alpha_type=`(/usr/sbin/psrinfo -v) 2>/dev/null |\
2898                sed -n -e 's/^.*The alpha \([^ ][^ ]*\).*processor.*$/\1/p' | sed -e 'q'`
2899            AT="${AP}${alpha_type}"
2900            AC="${AP}"
2901            #   determine system
2902            v=`echo "${UNAME_RELEASE}" | sed -e 's;^[VTX];;'`
2903            ST="[HP ]Tru64 ${v}"
2904            SP="${ST}"
2905            SC="OSF1"
2906            ;;
2907
2908        #   IBM AIX
2909        *:AIX:* )
2910            cpu_arch=rs6000
2911            if [ -x /usr/sbin/lsdev -a -x /usr/sbin/lsattr ]; then
2912                cpu_id=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
2913                if [ ".`/usr/sbin/lsattr -El ${cpu_id} | grep -i powerpc`" != . ]; then
2914                    cpu_arch=powerpc
2915                fi
2916            elif [ -d /QOpenSys ]; then
2917                #   IBM i5/OS (aka OS/400) with PASE (Portable Application Solutions Environment)
2918                cpu_arch=powerpc
2919            fi
2920            if [ -x /usr/bin/oslevel ]; then
2921                os_level=`/usr/bin/oslevel`
2922            else
2923                os_level="`uname -v`.`uname -r`"
2924            fi
2925            os_level=`echo "${os_level}" |\
2926                      sed -e 's;^\([0-9][0-9]*\.[0-9][0-9]*\)\(\.[0-9][0-9]*\)\(.*\)$;<\1>\2[\3];' \
2927                          -e 's;^\([0-9][0-9]*\.[0-9][0-9]*\)\(.*\)$;<\1>\2;'`
2928            AT="${cpu_arch}"
2929            AP="${AT}"
2930            AC="${AP}"
2931            ST="[IBM ]<AIX >${os_level}"
2932            SP="${ST}"
2933            case "${os_level}" in
2934                [12]* ) SC="SVR2" ;;
2935                *     ) SC="SVR4" ;;
2936            esac
2937            ;;
2938
2939        #   Apple MacOS X Darwin
2940        *:Darwin:* )
2941            AT=`uname -p`
2942            case "${AT}" in
2943                powerpc ) AT="PPC" ;;
2944            esac
2945            AP="${AT}"
2946            AC="${AP}"
2947            case "${AC}" in
2948                i?86 ) AC="iX86" ;;
2949            esac
2950            ST="[Apple ]${UNAME_SYSTEM} ${UNAME_RELEASE}"
2951            SP="${ST}"
2952            SC="4.4BSD/Mach3"
2953            ;;
2954
2955        #   TODO ...ADD YOUR NEW PLATFORM CHECK HERE... TODO
2956        # *:XXX:* )
2957        #   ...
2958        #   ;;
2959
2960        #   ...A STILL UNKNOWN PLATFORM...
2961        * )
2962            AT=`echo "${UNAME_MACHINE}" | sed -e "s; ;${opt_C};g"`
2963            AP="${AT}"
2964            AC="${AP}"
2965            v=`echo "${UNAME_RELEASE}" |\
2966               sed -e 's/^/#/' \
2967                   -e 's/^#[^0-9]*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*$/\1/' \
2968                   -e 's/^#[^0-9]*\([0-9][0-9]*\.[0-9][0-9]*\).*$/\1/' \
2969                   -e 's/^#[^0-9]*\([0-9][0-9]*\).*$/\1/' \
2970                   -e 's/^#.*$/?/'`
2971            ST="${UNAME_SYSTEM} ${v}"
2972            SP="${ST}"
2973            SC="${SP}"
2974            ;;
2975
2976    esac
2977
2978    #   provide fallback values
2979    [ ".$AT" = . ] && AT="${AP:-${AC}}"
2980    [ ".$AP" = . ] && AP="${AT:-${AC}}"
2981    [ ".$AC" = . ] && AC="${AP:-${AT}}"
2982    [ ".$ST" = . ] && ST="${SP:-${SC}}"
2983    [ ".$SP" = . ] && SP="${ST:-${SC}}"
2984    [ ".$SC" = . ] && SC="${SP:-${ST}}"
2985
2986    #   support explicit enforced verbose/concise output
2987    if [ ".$opt_v" = .yes ]; then
2988        opt_F=`echo ":$opt_F" | sed -e 's/^://' -e 's/%\([as][cpt]\)/%[\1]/g'`
2989    elif [ ".$opt_c" = .yes ]; then
2990        opt_F=`echo ":$opt_F" | sed -e 's/^://' -e 's/%\([as][cpt]\)/%<\1>/g'`
2991    fi
2992
2993    #   provide verbose and concise variants
2994    AC_V=""; AC_N=""; AC_C=""
2995    AP_V=""; AP_N=""; AP_C=""
2996    AT_V=""; AT_N=""; AT_C=""
2997    SC_V=""; SC_N=""; SC_C=""
2998    SP_V=""; SP_N=""; SP_C=""
2999    ST_V=""; ST_N=""; ST_C=""
3000    for var_lc in at ap ac st sp sc; do
3001        case "$opt_F" in
3002            *"%[${val_lc}]"* | *"%{${val_lc}}"* | *"%${val_lc}"* | *"%<${val_lc}>"* )
3003            var_uc=`util_upper "$var_lc"`
3004            eval "val=\"\$${var_uc}\""
3005            val_V=""; val_N=""; val_C=""
3006            case "$opt_F" in
3007                *"%[${var_lc}]"* )
3008                    val_V=`echo ":$val" | \
3009                           sed -e 's/^://' \
3010                               -e 's;\[\([^]]*\)\];\1;g' \
3011                               -e 's;<\([^>]*\)>;\1;g' \
3012                               -e "s; ;��;g" \
3013                               -e "s;/;%%;g" \
3014                               -e "s;��;${opt_S};g" \
3015                               -e "s;%%;${opt_C};g"`
3016                    eval "${var_uc}_V=\"\${val_V}\""
3017                    ;;
3018            esac
3019            case "$opt_F" in
3020                *"%{${var_lc}}"* | *"%${var_lc}"* )
3021                    val_N=`echo ":$val" | \
3022                           sed -e 's/^://' \
3023                               -e 's;\[\([^]]*\)\];;g' \
3024                               -e 's;<\([^>]*\)>;\1;g' \
3025                               -e "s; ;��;g" \
3026                               -e "s;/;%%;g" \
3027                               -e "s;��;${opt_S};g" \
3028                               -e "s;%%;${opt_C};g"`
3029                    eval "${var_uc}_N=\"\${val_N}\""
3030                    ;;
3031            esac
3032            case "$opt_F" in
3033                *"%<${var_lc}>"* )
3034                    val_C=`echo ":$val" | \
3035                           sed -e 's/^://' \
3036                               -e 's;\[\([^]]*\)\];;g' \
3037                               -e 's;[^<]*<\([^>]*\)>[^<]*;\1;g' \
3038                               -e "s; ;��;g" \
3039                               -e "s;/;%%;g" \
3040                               -e "s;��;${opt_S};g" \
3041                               -e "s;%%;${opt_C};g"`
3042                    eval "${var_uc}_C=\"\${val_C}\""
3043                    ;;
3044            esac
3045            ;;
3046        esac
3047    done
3048
3049    #   create output string
3050    output=`echo ":$opt_F" |\
3051            sed -e "s/^://" \
3052                -e "s;%\\[ac\\];${AC_V};g" \
3053                -e "s;%{ac};${AC_N};g" \
3054                -e "s;%ac;${AC_N};g" \
3055                -e "s;%<ac>;${AC_C};g" \
3056                -e "s;%\\[ap\\];${AP_V};g" \
3057                -e "s;%{ap};${AP_N};g" \
3058                -e "s;%ap;${AP_N};g" \
3059                -e "s;%<ap>;${AP_C};g" \
3060                -e "s;%\\[at\\];${AT_V};g" \
3061                -e "s;%{at};${AT_N};g" \
3062                -e "s;%at;${AT_N};g" \
3063                -e "s;%<at>;${AT_C};g" \
3064                -e "s;%\\[sc\\];${SC_V};g" \
3065                -e "s;%{sc};${SC_N};g" \
3066                -e "s;%sc;${SC_N};g" \
3067                -e "s;%<sc>;${SC_C};g" \
3068                -e "s;%\\[sp\\];${SP_V};g" \
3069                -e "s;%{sp};${SP_N};g" \
3070                -e "s;%sp;${SP_N};g" \
3071                -e "s;%<sp>;${SP_C};g" \
3072                -e "s;%\\[st\\];${ST_V};g" \
3073                -e "s;%{st};${ST_N};g" \
3074                -e "s;%st;${ST_N};g" \
3075                -e "s;%<st>;${ST_C};g" \
3076                -e 's/\\\\n/^/g' |\
3077             tr '^' '\012'`
3078
3079    #   support lower/upper-case mapping
3080    if [ ".$opt_L" = .yes ]; then
3081        output=`util_lower "$output"`
3082    elif [ ".$opt_U" = .yes ]; then
3083        output=`util_upper "$output"`
3084    fi
3085
3086    #   display output string
3087    if [ ".$opt_n" = .yes ]; then
3088        echo . | awk '{ printf("%s", output); }' output="$output"
3089    else
3090        echo "$output"
3091    fi
3092
3093    shtool_exit 0
3094    ;;
3095
3096arx )
3097    ##
3098    ##  arx -- Extended archive command
3099    ##  Copyright (c) 1999-2006 Ralf S. Engelschall <rse@engelschall.com>
3100    ##
3101
3102    ar_prg="$opt_C"
3103    ar_cmd="$1"; shift
3104    archive="$1"; shift
3105    files="$*"
3106
3107    #   walk through the file list and expand archives members
3108    ar_tmpdir=`echo $archive | sed -e 's;[^/]*$;.arx;'`
3109    nfiles=''
3110    if [ ".$files" != . ]; then
3111        for file in $files; do
3112            if [ ! -f $file ]; then
3113                echo "$msgprefix:Error: input file not found: $file" 1>&2
3114                shtool_exit 1
3115            fi
3116            case $file in
3117                *.a )
3118                    if [ ! -d $ar_tmpdir ]; then
3119                        if [ ".$opt_t" = .yes ]; then
3120                            echo "mkdir $ar_tmpdir" 1>&2
3121                        fi
3122                        mkdir $ar_tmpdir
3123                    fi
3124                    case $ar_tmpdir in
3125                         .arx )
3126                             from="../$file"
3127                             ;;
3128                         * )
3129                             dir=`echo $file | sed -e 's;[^/]*$;;' -e 's;\(.\)/$;\1;' -e 's;^$;.;'`
3130                             base=`echo $file | sed -e 's;.*/\([^/]*\)$;\1;'`
3131                             from="`cd $dir; pwd`/$base"
3132                             ;;
3133                    esac
3134                    if [ ".$opt_t" = .yes ]; then
3135                        echo "(cd $ar_tmpdir && $ar_prg x $from)" 1>&2
3136                    fi
3137                    (cd $ar_tmpdir && eval $ar_prg x $from)
3138                    if [ $? -ne 0 ]; then
3139                        echo "$msgprefix:Error: member extraction failed for archive: $file" 1>&2
3140                        shtool_exit 1
3141                    fi
3142                    for member in - `eval $ar_prg t $file | sed -e '/_\.SYMDEF/d'`; do
3143                        [ ".$member" = .- ] && continue
3144                        nfiles="$nfiles $ar_tmpdir/$member"
3145                    done
3146                    ;;
3147                * )
3148                    nfiles="$nfiles $file"
3149                    ;;
3150            esac
3151        done
3152    fi
3153
3154    #   run the final archive command
3155    if [ ".$opt_t" = .yes ]; then
3156        echo "$ar_prg $ar_cmd $archive $nfiles" 1>&2
3157    fi
3158    eval $ar_prg $ar_cmd $archive $nfiles
3159    if [ $? -ne 0 ]; then
3160        echo "$msgprefix:Error: archive command failed" 1>&2
3161        shtool_exit $?
3162    fi
3163
3164    #   cleanup and die gracefully
3165    if [ -d $ar_tmpdir ]; then
3166        if [ ".$opt_t" = .yes ]; then
3167            echo "rm -rf $ar_tmpdir" 1>&2
3168        fi
3169        rm -rf $ar_tmpdir
3170    fi
3171
3172    shtool_exit 0
3173    ;;
3174
3175slo )
3176    ##
3177    ##  slo -- Separate linker options by library class
3178    ##  Copyright (c) 1998-2006 Ralf S. Engelschall <rse@engelschall.com>
3179    ##
3180
3181    DIFS="$IFS"
3182
3183    #   parse out -L and -l options from command line
3184    DIRS=''
3185    LIBS=''
3186    ARGV=''
3187    optprev=''
3188    for opt
3189    do
3190        #   concatenate with previous option if exists
3191        if [ ".$optprev" != . ]; then
3192            opt="${optprev}${opt}";
3193            optprev=''
3194        fi
3195        #   remember options for arg if used stand-alone
3196        if [ ".$opt" = ".-L" ] || [ ".$opt" = ".-l" ]; then
3197            optprev="$opt"
3198            continue;
3199        fi
3200        #   split argument into option plus option argument
3201        arg="`echo $opt | cut -c3-`"
3202        opt="`echo $opt | cut -c1-2`"
3203        #   store into containers
3204        case $opt in
3205            -L) DIRS="$DIRS:$arg" ;;
3206            -l) LIBS="$LIBS:$arg" ;;
3207             *) ARGV="$ARGV $opt" ;;
3208        esac
3209    done
3210
3211    #   set linker default directories
3212    DIRS_DEFAULT='/lib:/usr/lib'
3213    if [ ".$LD_LIBRARY_PATH" != . ]; then
3214        DIRS_DEFAULT="$DIRS_DEFAULT:$LD_LIBRARY_PATH"
3215    fi
3216
3217    #   sort options by class
3218    DIRS_OBJ=''
3219    LIBS_OBJ=''
3220    DIRS_PIC=''
3221    LIBS_PIC=''
3222    DIRS_DSO=''
3223    LIBS_DSO=''
3224
3225    #    for each library...
3226    OIFS="$IFS"; IFS=':'
3227    for lib in $LIBS; do
3228        [ ".$lib" = . ] && continue
3229
3230        found='no'
3231        found_indefdir='no'
3232        found_type=''
3233        found_dir=''
3234
3235        #    for each directory...
3236        OIFS2="$IFS"; IFS=":$DIFS"
3237        for dir in ${DIRS} switch-to-defdirs ${DIRS_DEFAULT}; do
3238            [ ".$dir" = . ] && continue
3239            [ ".$dir" = .switch-to-defdirs ] && found_indefdir=yes
3240            [ ! -d $dir ] && continue
3241
3242            #    search the file
3243            OIFS3="$IFS"; IFS="$DIFS"
3244            for file in '' `cd $dir && env -i /bin/ls lib${lib}.* 2>/dev/null`; do
3245                 [ ".$file" = . ] && continue
3246                 case $file in
3247                     *.so|*.so.[0-9]*|*.sl|*.sl.[0-9]* )
3248                          found=yes;
3249                          found_type=DSO;
3250                          break
3251                          ;;
3252                     *.lo|*.la )
3253                          found=yes;
3254                          found_type=PIC
3255                          ;;
3256                     *.a )
3257                          if [ ".$found_type" = . ]; then
3258                              found=yes
3259                              found_type=OBJ
3260                          fi
3261                          ;;
3262                 esac
3263            done
3264            IFS="$OIFS3"
3265            if [ ".$found" = .yes ]; then
3266                found_dir="$dir"
3267                break
3268            fi
3269        done
3270        IFS="$OIFS2"
3271
3272        if [ ".$found" = .yes ]; then
3273            if [ ".$found_indefdir" != .yes ]; then
3274                eval "dirlist=\"\${DIRS_${found_type}}:\""
3275                case "$dirlist" in
3276                    *:$found_dir:* ) ;;
3277                    * ) eval "DIRS_${found_type}=\"\$DIRS_${found_type}:${found_dir}\"" ;;
3278                esac
3279                eval "LIBS_${found_type}=\"\$LIBS_${found_type}:$lib\""
3280            else
3281                eval "LIBS_${found_type}=\"\$LIBS_${found_type}:$lib\""
3282            fi
3283        else
3284            LIBS_OBJ="$LIBS_OBJ:$lib"
3285            #dirlist="`echo $DIRS $DIRS_DEFAULT | sed -e 's/:/ /g'`"
3286            #echo "slo:Warning: library \"$lib\" not found in any of the following dirs:" 2>&1
3287            #echo "slo:Warning: $dirlist" 1>&1
3288        fi
3289    done
3290    IFS="$OIFS"
3291
3292    #   also pass-through unused dirs even if it's useless
3293    OIFS="$IFS"; IFS=':'
3294    for dir in $DIRS; do
3295        dirlist="${DIRS_OBJ}:${DIRS_PIC}:${DIRS_DSO}:"
3296        case "$dirlist" in
3297            *:$dir:* ) ;;
3298            * ) DIRS_OBJ="$DIRS_OBJ:$dir" ;;
3299        esac
3300    done
3301    IFS="$OIFS"
3302
3303    #   reassemble the options but separated by type
3304    for type in OBJ PIC DSO; do
3305        OIFS="$IFS"; IFS=':'
3306        eval "libs=\"\$LIBS_${type}\""
3307        opts=''
3308        for lib in $libs; do
3309            [ ".$lib" = . ] && continue
3310            opts="$opts -l$lib"
3311        done
3312        eval "LIBS_${type}=\"$opts\""
3313
3314        eval "dirs=\"\$DIRS_${type}\""
3315        opts=''
3316        for dir in $dirs; do
3317            [ ".$dir" = . ] && continue
3318            opts="$opts -L$dir"
3319        done
3320        eval "DIRS_${type}=\"$opts\""
3321        IFS="$OIFS"
3322    done
3323
3324    #   give back results
3325    for var in ARGV DIRS_OBJ LIBS_OBJ DIRS_PIC LIBS_PIC DIRS_DSO LIBS_DSO; do
3326        eval "val=\"\$${var}\""
3327        val="`echo $val | sed -e 's/^ *//'`"
3328        echo "${opt_p}${var}=\"${val}\""
3329    done
3330
3331    shtool_exit 0
3332    ;;
3333
3334scpp )
3335    ##
3336    ##  scpp -- Sharing C Pre-Processor
3337    ##  Copyright (c) 1999-2006 Ralf S. Engelschall <rse@engelschall.com>
3338    ##
3339
3340    srcs="$*"
3341    output="${opt_o}.n"
3342
3343    #   find a reasonable Awk
3344    awk=''
3345    paths=`echo $PATH |\
3346           sed -e 's%/*:%:%g' -e 's%/$%%' \
3347               -e 's/^:/.:/' -e 's/::/:.:/g' -e 's/:$/:./' \
3348               -e 's/:/ /g'`
3349    for name in gawk nawk awk; do
3350        for path in $paths; do
3351            if [ -r "$path/$name" ]; then
3352                awk="$path/$name"
3353                break
3354            fi
3355        done
3356        if [ ".$awk" != . ]; then
3357            break
3358        fi
3359    done
3360    if [ ".$awk" = . ]; then
3361        echo "$msgprefix:Error: cannot find a reasonable Awk" 1>&2
3362        shtool_exit 1
3363    fi
3364
3365    #   parse source file(s)
3366    if [ ".$opt_v" = .yes ]; then
3367        echo "Parsing:" | $awk '{ printf("%s", $0); }' 1>&2
3368    fi
3369    for src in $srcs; do
3370        if [ ".$opt_v" = .yes ]; then
3371            echo $src | $awk '{ printf(" %s", $0); }' 1>&2
3372        fi
3373        if [ ".$opt_f" != . ]; then
3374            inputcmd="sed"
3375            OIFS="$IFS"; IFS="$ASC_NL"; set -- $opt_f; IFS="$OIFS"
3376            for e
3377            do
3378                inputcmd="$inputcmd -e '$e'"
3379            done
3380            inputcmd="$inputcmd '$src'"
3381        else
3382            inputcmd="cat '$src'"
3383        fi
3384        eval $inputcmd |\
3385        $awk '
3386           BEGIN {
3387               ln    = 0;
3388               fln   = 0;
3389               level = 0;
3390               mode  = "";
3391               store = "";
3392           }
3393           {
3394               ln++;
3395           }
3396           /^#if.*/ {
3397               level++;
3398           }
3399           /^#if [a-zA-Z_][a-zA-Z0-9_]* *$/ {
3400               if ($2 == define) {
3401                   mode = "D";
3402                   printf("D:#line %d \"%s\"\n", ln, src);
3403                   next;
3404               }
3405           }
3406           /^#endif.*/ {
3407               level--;
3408               if (mode == "D" && level == 0) {
3409                   mode = "";
3410                   next;
3411               }
3412           }
3413           /^[a-zA-Z_][a-zA-Z0-9_].*;.*/ {
3414               if ($1 == class) {
3415                   printf("V:#line %d \"%s\"\n", ln, src);
3416                   printf("V:%s\n", $0);
3417                   printf("J:%s\n", $0);
3418                   next;
3419               }
3420           }
3421           /^[a-zA-Z_][a-zA-Z0-9_].*=.*/ {
3422               if ($1 == class) {
3423                   printf("V:#line %d \"%s\"\n", ln, src);
3424                   printf("V:%s\n", $0);
3425                   printf("J:%s\n", $0);
3426                   next;
3427               }
3428           }
3429           /^[a-zA-Z_][a-zA-Z0-9_]*/ {
3430               if ($1 == class) {
3431                   fln = ln;
3432                   store = $0;
3433                   mode = "F";
3434                   next;
3435               }
3436           }
3437           /^\{ *$/ {
3438               if (mode == "F") {
3439                   printf("F:#line %d \"%s\"\n", fln, src);
3440                   printf("F:%s;\n", store);
3441                   printf("I:%s;\n", store);
3442                   store = "";
3443                   mode = "";
3444                   next;
3445               }
3446           }
3447           {
3448               if (mode == "D")
3449                   printf("D:%s\n", $0);
3450               else if (mode == "F")
3451                   store = store " " $0;
3452           }
3453        ' "src=$src" "define=$opt_D" "class=$opt_C" >>$tmpfile
3454    done
3455    if [ ".$opt_v" = .yes ]; then
3456        echo "" 1>&2
3457    fi
3458
3459    #   start generating output header
3460    echo "/* $opt_o -- autogenerated from $opt_t, DO NOT EDIT! */" >$output
3461    echo "#line 1 \"$opt_t\"" >>$output
3462    sed <$opt_t -e "1,/^${opt_M} *\$/p" -e 'd' |\
3463    sed -e "/^${opt_M} *\$/d" >>$output
3464
3465    #   merge in the define blocks
3466    grep '^D:' $tmpfile | sed -e 's/^D://' >>$output
3467
3468    #   generate standard prolog
3469    echo "#line 1 \"_ON_THE_FLY_\"" >>$output
3470    echo "" >>$output
3471    echo "/* make sure the scpp source extensions are skipped */" >>$output
3472    echo "#define $opt_D 0" >>$output
3473    echo "#define $opt_C /**/" >>$output
3474
3475    #   generate namespace hiding for variables
3476    echo "" >>$output
3477    echo "/* move intern variables to hidden namespace */" >>$output
3478    grep '^J:' $tmpfile | sed >>$output \
3479        -e 's/^J://' \
3480        -e 's/  */ /g' \
3481        -e 's/^[^=;]*[ *]\([a-zA-Z0-9_]*\)\[\];.*$/#define \1 __\1/' \
3482        -e 's/^[^=;]*[ *]\([a-zA-Z0-9_]*\)\[\] =.*$/#define \1 __\1/' \
3483        -e 's/^[^=;]*[ *]\([a-zA-Z0-9_]*\);.*$/#define \1 __\1/' \
3484        -e 's/^[^=;]*[ *]\([a-zA-Z0-9_]*\) =.*$/#define \1 __\1/'
3485
3486    #   generate namespace hiding for functions
3487    echo "" >>$output
3488    echo "/* move intern functions to hidden namespace */" >>$output
3489    grep '^I:' $tmpfile | sed >>$output \
3490        -e 's/^I://' \
3491        -e 's/\([ (]\) */\1/g' \
3492        -e 's/ *\([),]\)/\1/g' \
3493        -e 's/^[^(]*[ *]\([a-zA-Z0-9_]*\)(.*$/#define \1 __\1/'
3494
3495    #   generate prototypes for variables
3496    echo "" >>$output
3497    echo "/* prototypes for intern variables */" >>$output
3498    grep '^V:' $tmpfile | sed >>$output \
3499        -e 's/^V://' \
3500        -e 's/  */ /g' \
3501        -e 's/^\([^=;]*[ *][a-zA-Z0-9_]*\[\]\);.*$/\1;/' \
3502        -e 's/^\([^=;]*[ *][a-zA-Z0-9_]*\[\]\) =.*$/\1;/' \
3503        -e 's/^\([^=;]*[ *][a-zA-Z0-9_]*\);.*$/\1;/' \
3504        -e 's/^\([^=;]*[ *][a-zA-Z0-9_]*\) =.*$/\1;/' \
3505        -e 's/ ;/;/g' \
3506        -e "s/^$opt_C /extern /"
3507
3508    #   generate prototypes for functions
3509    echo "" >>$output
3510    echo "/* prototypes for intern functions */" >>$output
3511    grep '^F:' $tmpfile | sed >>$output \
3512        -e 's/^F://' \
3513        -e 's/\([ (]\) */\1/g' \
3514        -e 's/ *\([),]\)/\1/g' \
3515        -e 's/\([* ]\)[a-zA-Z0-9_]*,/\1,/g' \
3516        -e 's/\([* ]\)[a-zA-Z0-9_]*);/\1);/g' \
3517        -e 's/(\*[a-zA-Z0-9_]*)(/(*)(/g' \
3518        -e 's/\([ (]\) */\1/g' \
3519        -e 's/ *\([),]\)/\1/g' \
3520        -e "s/^$opt_C /extern /"
3521
3522    #   finish generating output header
3523    n=`(echo ''; sed <$opt_t -e "1,/^${opt_M} *\$/p" -e 'd') |\
3524       wc -l | sed -e 's;^ *\([0-9]*\) *$;\1;'`
3525    echo "#line $n \"$opt_t\"" >>$output
3526    sed <$opt_t -e "/^${opt_M} *\$/,\$p" -e 'd' |\
3527    sed -e "/^${opt_M} *\$/d" >>$output
3528
3529    #   create final output file
3530    if [ -f $opt_o ]; then
3531        if [ ".$opt_p" = .yes ]; then
3532            grep -v '^#line' $opt_o  >$tmpfile.o
3533            grep -v '^#line' $output >$tmpfile.n
3534            out_old="$tmpfile.o"
3535            out_new="$tmpfile.n"
3536        else
3537            out_old="$opt_o"
3538            out_new="$output"
3539        fi
3540        if cmp -s $out_old $out_new; then
3541            :
3542        else
3543            cp $output $opt_o
3544        fi
3545    else
3546        cp $output $opt_o
3547    fi
3548    rm -f $output
3549    rm -f $tmpfile $tmpfile.* >/dev/null 2>&1
3550
3551    shtool_exit 0
3552    ;;
3553
3554version )
3555    ##
3556    ##  version -- Maintain a version information file
3557    ##  Copyright (c) 1994-2006 Ralf S. Engelschall <rse@engelschall.com>
3558    ##
3559
3560    file="$1"
3561
3562    #   determine prefix and name
3563    name="$opt_n"
3564    prefix="$opt_p"
3565
3566    #   determine current version
3567    triple="$opt_s"
3568    if [ ".$triple" != . ]; then
3569        #   use given triple
3570        if [ ".`echo $triple | grep '[0-9]*.[0-9]*[sabp.][0-9]*'`" = . ]; then
3571            echo "$msgprefix:Error: invalid argument to option \`-s': \`$opt_s'" 1>&2
3572            shtool_exit 1
3573        fi
3574        eval `echo $triple |\
3575              sed -e 's%\([0-9]*\)\.\([0-9]*\)\([sabp.]\)\([0-9]*\).*%\
3576              ver="\1";rev="\2";typ="\3";lev="\4"%'`
3577        tim=calc
3578    elif [ -r $file ]; then
3579        #   determine triple from given file
3580        eval `grep 'Version [0-9]*.[0-9]*[sabp.][0-9]* ([0-9]*-[a-zA-Z]*-[0-9]*)' $file |\
3581              sed -e 's%.*Version \([0-9]*\)\.\([0-9]*\)\([sabp.]\)\([0-9]*\) (\([0-9]*-[a-zA-Z]*-[0-9]*\)).*%\
3582              ver="\1";rev="\2";typ="\3";lev="\4";tim="\5"%' -e 'q'`
3583    else
3584        #   intialise to first version
3585        ver=0
3586        rev=1
3587        typ=.
3588        lev=0
3589        tim=calc
3590    fi
3591
3592    #   determine new version in batch
3593    if [ ".$opt_i" != . ]; then
3594        case $opt_i in
3595            v ) ver=`expr $ver + 1`
3596                rev=0
3597                lev=0
3598                ;;
3599            r ) rev=`expr $rev + 1`
3600                lev=0
3601                ;;
3602            l ) lev=`expr $lev + 1`
3603                ;;
3604            * ) echo "$msgprefix:Error: invalid argument to option \`-i': \`$opt_i'" 1>&2
3605                shtool_exit 1
3606                ;;
3607        esac
3608        tim=calc
3609    fi
3610
3611    #   determine new version interactively
3612    if [ ".$opt_e" = .yes ]; then
3613        echo "old version: ${ver}.${rev}${typ}${lev}"
3614        while [ 1 ]; do
3615            echo dummy | awk '{ printf("new version: "); }'
3616            read triple
3617            case $triple in
3618                [0-9]*.[0-9]*[sabp.][0-9]* )
3619                    ;;
3620                * ) echo "$msgprefix:Error: invalid version string entered: \`$triple'" 1>&2
3621                    continue
3622                    ;;
3623            esac
3624            break
3625        done
3626        eval `echo $triple |\
3627              sed -e 's%^\([0-9]*\)\.\([0-9]*\)\([sabp.]\)\([0-9]*\)$%\
3628              ver="\1";rev="\2";typ="\3";lev="\4"%'`
3629        tim=calc
3630    fi
3631
3632    #   determine hexadecimal and libtool value of version
3633    case $typ in
3634        a     ) typnum=0;  levnum=$lev ;;
3635        b     ) typnum=1;  levnum=$lev ;;
3636        p | . ) typnum=2;  levnum=$lev ;;
3637        s     ) typnum=15; levnum=255  ;; # snapshots are special
3638    esac
3639    hex=`echo "$ver:$rev:$typnum:$levnum" |\
3640         awk -F: '{ printf("0x%x%02x%1x%02x", $1, $2, $3, $4); }' |\
3641         tr 'abcdef' 'ABCDEF'`
3642    ltv=`echo "$ver:$rev:$typnum:$levnum" |\
3643         awk -F: '{ printf("%d:%d", $1*10 + $2, $3*10 + $4); }'`
3644
3645    #   determine date
3646    if [ ".$tim" = .calc ]; then
3647        day=`date '+%d'`
3648        month=`date '+%m'`
3649        year=`date '+%Y' 2>/dev/null`
3650        if [ ".$time_year" = . ]; then
3651            year=`date '+%y'`
3652            case $year in
3653                [5-9][0-9]) year="19$year" ;;
3654                [0-4][0-9]) year="20$year" ;;
3655            esac
3656        fi
3657        case $month in
3658            1|01) month='Jan' ;;
3659            2|02) month='Feb' ;;
3660            3|03) month='Mar' ;;
3661            4|04) month='Apr' ;;
3662            5|05) month='May' ;;
3663            6|06) month='Jun' ;;
3664            7|07) month='Jul' ;;
3665            8|08) month='Aug' ;;
3666            9|09) month='Sep' ;;
3667              10) month='Oct' ;;
3668              11) month='Nov' ;;
3669              12) month='Dec' ;;
3670        esac
3671        tim="${day}-${month}-${year}"
3672    fi
3673
3674    #   perform result actions
3675    mode=show
3676    if [ ".$opt_i" != . ]; then
3677        mode=edit
3678    elif [ ".$opt_e" = .yes ]; then
3679        mode=edit
3680    elif [ ".$opt_s" != . ]; then
3681        mode=edit
3682    fi
3683    if [ ".$mode" = .show ]; then
3684        #   just display the current version
3685        case $opt_d in
3686            short )
3687                echo "${ver}.${rev}${typ}${lev}"
3688                ;;
3689            long )
3690                echo "${ver}.${rev}${typ}${lev} ($tim)"
3691                ;;
3692            libtool )
3693                echo "${ltv}"
3694                ;;
3695            hex )
3696                echo "${hex}"
3697                ;;
3698            * ) echo "$msgprefix:Error: invalid argument to option \`-d': \`$opt_d'" 1>&2
3699                shtool_exit 1
3700                ;;
3701        esac
3702    else
3703        #   update the version file
3704
3705        #   pre-generate various strings
3706        triple="${ver}.${rev}${typ}${lev}"
3707        vHex="$hex"
3708        vShort="${triple}"
3709        vLong="${triple} (${tim})"
3710        vTeX="This is ${name}, Version ${triple} (${tim})"
3711        vGNU="${name} ${triple} (${tim})"
3712        vWeb="${name}/${triple}"
3713        vSCCS="@(#)${name} ${triple} (${tim})"
3714        vRCS="\$Id: ${name} ${triple} (${tim}) \$"
3715
3716        #   determine string out of filename
3717        #   (do NOT try to optimize this in any way because of portability)
3718        filestr=`util_upper "$file" | tr './%+' '____' | sed -e 's/-/_/g'`
3719
3720        #   generate uppercase prefix
3721        prefixupper=`util_upper "$prefix"`
3722
3723        #   create the version file according the the selected language
3724        echo "new version: ${vLong}"
3725
3726        cp /dev/null $file
3727        case $opt_l in
3728            txt )
3729                echo >>$file ""
3730                echo >>$file "  ${file} -- Version Information for ${name} (syntax: Text)"
3731                echo >>$file "  [automatically generated and maintained by GNU shtool]"
3732                echo >>$file ""
3733                echo >>$file "  $vTeX"
3734                echo >>$file ""
3735                ;;
3736            c )
3737                echo >>$file "/*"
3738                echo >>$file "**  ${file} -- Version Information for ${name} (syntax: C/C++)"
3739                echo >>$file "**  [automatically generated and maintained by GNU shtool]"
3740                echo >>$file "*/"
3741                echo >>$file ""
3742                echo >>$file "#ifdef _${filestr}_AS_HEADER_"
3743                echo >>$file ""
3744                echo >>$file "#ifndef _${filestr}_"
3745                echo >>$file "#define _${filestr}_"
3746                echo >>$file ""
3747                echo >>$file "#define ${prefixupper}VERSION ${vHex}"
3748                echo >>$file ""
3749                echo >>$file "typedef struct {"
3750                echo >>$file "    const int   v_hex;"
3751                echo >>$file "    const char *v_short;"
3752                echo >>$file "    const char *v_long;"
3753                echo >>$file "    const char *v_tex;"
3754                echo >>$file "    const char *v_gnu;"
3755                echo >>$file "    const char *v_web;"
3756                echo >>$file "    const char *v_sccs;"
3757                echo >>$file "    const char *v_rcs;"
3758                echo >>$file "} ${prefix}version_t;"
3759                echo >>$file ""
3760                echo >>$file "extern ${prefix}version_t ${prefix}version;"
3761                echo >>$file ""
3762                echo >>$file "#endif /* _${filestr}_ */"
3763                echo >>$file ""
3764                echo >>$file "#else /* _${filestr}_AS_HEADER_ */"
3765                echo >>$file ""
3766                echo >>$file "#define _${filestr}_AS_HEADER_"
3767                echo >>$file "#include \"${file}\""
3768                echo >>$file "#undef  _${filestr}_AS_HEADER_"
3769                echo >>$file ""
3770                echo >>$file "${prefix}version_t ${prefix}version = {"
3771                echo >>$file "    ${vHex},"
3772                echo >>$file "    \"${vShort}\","
3773                echo >>$file "    \"${vLong}\","
3774                echo >>$file "    \"${vTeX}\","
3775                echo >>$file "    \"${vGNU}\","
3776                echo >>$file "    \"${vWeb}\","
3777                echo >>$file "    \"${vSCCS}\","
3778                echo >>$file "    \"${vRCS}\""
3779                echo >>$file "};"
3780                echo >>$file ""
3781                echo >>$file "#endif /* _${filestr}_AS_HEADER_ */"
3782                echo >>$file ""
3783                ;;
3784            m4 )
3785                echo >>$file "##"
3786                echo >>$file "##  ${file} -- Version Information for ${name} (syntax: M4)"
3787                echo >>$file "##  [automatically generated and maintained by GNU shtool]"
3788                echo >>$file "##"
3789                echo >>$file ""
3790                echo >>$file "m4_define([v_hex],   [${vHex}])"
3791                echo >>$file "m4_define([v_short], [${vShort}])"
3792                echo >>$file "m4_define([v_long],  [${vLong}])"
3793                echo >>$file "m4_define([v_tex],   [${vTeX}])"
3794                echo >>$file "m4_define([v_gnu],   [${vGNU}])"
3795                echo >>$file "m4_define([v_web],   [${vWeb}])"
3796                echo >>$file "m4_define([v_sccs],  [${vSCCS}])"
3797                echo >>$file "m4_define([v_rcs],   [${vRCS}])"
3798                echo >>$file ""
3799                ;;
3800            perl )
3801                echo >>$file "##"
3802                echo >>$file "##  ${file} -- Version Information for ${name} (syntax: Perl)"
3803                echo >>$file "##  [automatically generated and maintained by GNU shtool]"
3804                echo >>$file "##"
3805                echo >>$file ""
3806                echo >>$file "our \$${prefix}version = {"
3807                echo >>$file "    'v_hex'   => ${vHex},"
3808                echo >>$file "    'v_short' => \"${vShort}\","
3809                echo >>$file "    'v_long'  => \"${vLong}\","
3810                echo >>$file "    'v_tex'   => \"${vTeX}\","
3811                echo >>$file "    'v_gnu'   => \"${vGNU}\","
3812                echo >>$file "    'v_web'   => \"${vWeb}\","
3813                echo >>$file "    'v_sccs'  => \"${vSCCS}\","
3814                echo >>$file "    'v_rcs'   => \"\\${vRCS}/\""
3815                echo >>$file "};"
3816                echo >>$file ""
3817                echo >>$file "1;"
3818                echo >>$file ""
3819                ;;
3820            python )
3821                echo >>$file "##"
3822                echo >>$file "##  ${file} -- Version Information for ${name} (syntax: Python)"
3823                echo >>$file "##  [automatically generated and maintained by GNU shtool]"
3824                echo >>$file "##"
3825                echo >>$file ""
3826                echo >>$file "class ${prefix}version:"
3827                echo >>$file "    v_hex       = ${vHex}"
3828                echo >>$file "    v_short     = \"${vShort}\""
3829                echo >>$file "    v_long      = \"${vLong}\""
3830                echo >>$file "    v_tex       = \"${vTeX}\""
3831                echo >>$file "    v_gnu       = \"${vGNU}\""
3832                echo >>$file "    v_web       = \"${vWeb}\""
3833                echo >>$file "    v_sccs      = \"${vSCCS}\""
3834                echo >>$file "    v_rcs       = \"${vRCS}\""
3835                echo >>$file ""
3836                ;;
3837            * ) echo "$msgprefix:Error: invalid argument to option \`-l': \`$opt_l'" 1>&2
3838                shtool_exit 1
3839                ;;
3840        esac
3841    fi
3842
3843    shtool_exit 0
3844    ;;
3845
3846path )
3847    ##
3848    ##  path -- Deal with program paths
3849    ##  Copyright (c) 1998-2006 Ralf S. Engelschall <rse@engelschall.com>
3850    ##
3851
3852    namelist="$*"
3853
3854    #   check whether the test command supports the -x option
3855    if [ -x /bin/sh ] 2>/dev/null; then
3856        minusx="-x"
3857    else
3858        minusx="-r"
3859    fi
3860
3861    #   split path string
3862    paths="`echo $opt_p |\
3863            sed -e 's/^:/.:/' \
3864                -e 's/::/:.:/g' \
3865                -e 's/:$/:./' \
3866                -e 's/:/ /g'`"
3867
3868    #   SPECIAL REQUEST
3869    #   translate forward to reverse path
3870    if [ ".$opt_r" = .yes ]; then
3871        if [ "x$namelist" = "x." ]; then
3872            rp='.'
3873        else
3874            rp=''
3875            for pe in `IFS="$IFS/"; echo $namelist`; do
3876                rp="../$rp"
3877            done
3878        fi
3879        echo $rp | sed -e 's:/$::'
3880        shtool_exit 0
3881    fi
3882
3883    #   SPECIAL REQUEST
3884    #   strip out directory or base name
3885    if [ ".$opt_d" = .yes ]; then
3886        echo "$namelist" |\
3887        sed -e 's;[^/]*$;;' -e 's;\(.\)/$;\1;'
3888        shtool_exit 0
3889    fi
3890    if [ ".$opt_b" = .yes ]; then
3891        echo "$namelist" |\
3892        sed -e 's;.*/\([^/]*\)$;\1;'
3893        shtool_exit 0
3894    fi
3895
3896    #   MAGIC SITUATION
3897    #   Perl Interpreter (perl)
3898    if [ ".$opt_m" = .yes ] && [ ".$namelist" = .perl ]; then
3899        rm -f $tmpfile >/dev/null 2>&1
3900        touch $tmpfile
3901        found=0
3902        pc=99
3903        for dir in $paths; do
3904            dir=`echo $dir | sed -e 's;/*$;;'`
3905            nc=99
3906            for name in perl perl5 miniperl; do
3907                 if [ $minusx "$dir/$name" ] && [ ! -d "$dir/$name" ]; then
3908                     perl="$dir/$name"
3909                     pv=`$perl -e 'printf("%.3f", $]);'`
3910                     echo "$pv:$pc:$nc:$perl" >>$tmpfile
3911                     found=1
3912                 fi
3913                 nc=`expr $nc - 1`
3914            done
3915            pc=`expr $pc - 1`
3916        done
3917        if [ $found = 1 ]; then
3918            perl="`cat $tmpfile | sort -r -u | sed -e 'q' | cut -d: -f4`"
3919            rm -f $tmpfile >/dev/null 2>&1
3920            echo "$perl"
3921            shtool_exit 0
3922        fi
3923        rm -f $tmpfile >/dev/null 2>&1
3924        shtool_exit 1
3925    fi
3926
3927    #   MAGIC SITUATION
3928    #   C pre-processor (cpp)
3929    if [ ".$opt_m" = .yes ] && [ ".$namelist" = .cpp ]; then
3930        echo >$tmpfile.c "#include <assert.h>"
3931        echo >>$tmpfile.c "Syntax Error"
3932        #   1. try the standard cc -E approach
3933        cpp="${CC-cc} -E"
3934        (eval "$cpp $tmpfile.c >/dev/null") 2>$tmpfile.out
3935        my_error=`grep -v '^ *+' $tmpfile.out`
3936        if [ ".$my_error" != . ]; then
3937            #   2. try the cc -E approach and GCC's -traditional-ccp option
3938            cpp="${CC-cc} -E -traditional-cpp"
3939            (eval "$cpp $tmpfile.c >/dev/null") 2>$tmpfile.out
3940            my_error=`grep -v '^ *+' $tmpfile.out`
3941            if [ ".$my_error" != . ]; then
3942                #   3. try a standalone cpp command in path and lib dirs
3943                for path in $paths /lib /usr/lib /usr/local/lib; do
3944                    path=`echo $path | sed -e 's;/*$;;'`
3945                    if [ $minusx "$path/cpp" ] && [ ! -d "$path/cpp" ]; then
3946                        cpp="$path/cpp"
3947                        break
3948                    fi
3949                done
3950                if [ ".$cpp" != . ]; then
3951                    (eval "$cpp $tmpfile.c >/dev/null") 2>$tmpfile.out
3952                    my_error=`grep -v '^ *+' $tmpfile.out`
3953                    if [ ".$my_error" != . ]; then
3954                        #   ok, we gave up...
3955                        cpp=''
3956                    fi
3957                fi
3958            fi
3959        fi
3960        rm -f $tmpfile >/dev/null 2>&1
3961        rm -f $tmpfile.c $tmpfile.out >/dev/null 2>&1
3962        if [ ".$cpp" != . ]; then
3963            echo "$cpp"
3964            shtool_exit 0
3965        fi
3966        shtool_exit 1
3967    fi
3968
3969    #   STANDARD SITUATION
3970    #   iterate over names
3971    for name in $namelist; do
3972        #   iterate over paths
3973        for path in $paths; do
3974            path=`echo $path | sed -e 's;/*$;;'`
3975            if [ $minusx "$path/$name" ] && [ ! -d "$path/$name" ]; then
3976                if [ ".$opt_s" != .yes ]; then
3977                    echo "$path/$name"
3978                fi
3979                shtool_exit 0
3980            fi
3981        done
3982    done
3983
3984    shtool_exit 1
3985    ;;
3986
3987esac
3988
3989shtool_exit 0
3990
3991