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