1#!/bin/sh
2##
3##  GNU shtool -- The GNU Portable Shell Tool
4##  Copyright (c) 1994-2007 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.7 (19-May-2007)
10##  Contents: all available modules
11##
12
13##
14##  This program is free software; you can redistribute it and/or modify
15##  it under the terms of the GNU General Public License as published by
16##  the Free Software Foundation; either version 2 of the License, or
17##  (at your option) any later version.
18##
19##  This program is distributed in the hope that it will be useful,
20##  but WITHOUT ANY WARRANTY; without even the implied warranty of
21##  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22##  General Public License for more details.
23##
24##  You should have received a copy of the GNU General Public License
25##  along with this program; if not, write to the Free Software
26##  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
27##  USA, or contact Ralf S. Engelschall <rse@engelschall.com>.
28##
29##  NOTICE: Given that you include this file verbatim into your own
30##  source tree, you are justified in saying that it remains separate
31##  from your package, and that this way you are simply just using GNU
32##  shtool. So, in this situation, there is no requirement that your
33##  package itself is licensed under the GNU General Public License in
34##  order to take advantage of GNU shtool.
35##
36
37##
38##  Usage: shtool [<options>] [<cmd-name> [<cmd-options>] [<cmd-args>]]
39##
40##  Available commands:
41##    echo       Print string with optional construct expansion
42##    mdate      Pretty-print modification time of a file or dir
43##    table      Pretty-print a field-separated list as a table
44##    prop       Display progress with a running propeller
45##    move       Move files with simultaneous substitution
46##    install    Install a program, script or datafile
47##    mkdir      Make one or more directories
48##    mkln       Make link with calculation of relative paths
49##    mkshadow   Make a shadow tree through symbolic links
50##    fixperm    Fix file permissions inside a source tree
51##    rotate     Logfile rotation
52##    tarball    Roll distribution tarballs
53##    subst      Apply sed(1) substitution operations
54##    platform   Platform Identification Utility
55##    arx        Extended archive command
56##    slo        Separate linker options by library class
57##    scpp       Sharing C Pre-Processor
58##    version    Maintain a version information file
59##    path       Deal with program paths
60##
61
62#   maximum Bourne-Shell compatibility
63if [ ".$ZSH_VERSION" != . ] && (emulate sh) >/dev/null 2>&1; then
64    #   reconfigure zsh(1)
65    emulate sh
66    NULLCMD=:
67    alias -g '${1+"$@"}'='"$@"'
68elif [ ".$BASH_VERSION" != . ] && (set -o posix) >/dev/null 2>&1; then
69    #   reconfigure bash(1)
70    set -o posix
71fi
72
73#   maximum independence of NLS nuisances
74for var in \
75    LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
76    LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
77    LC_TELEPHONE LC_TIME
78do
79    if (set +x; test -z "`(eval $var=C; export $var) 2>&1`"); then
80        eval $var=C; export $var
81    else
82        unset $var
83    fi
84done
85
86#   initial command line handling
87if [ $# -eq 0 ]; then
88    echo "$0:Error: invalid command line" 1>&2
89    echo "$0:Hint:  run \`$0 -h' for usage" 1>&2
90    exit 1
91fi
92if [ ".$1" = ".-h" ] || [ ".$1" = ".--help" ]; then
93    echo "This is GNU shtool, version 2.0.7 (19-May-2007)"
94    echo 'Copyright (c) 1994-2007 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.7 (19-May-2007)"
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-2007 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-2007 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-2007 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-2007 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-2007 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-2007 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-2007 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-2007 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-2007 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-2007 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-2007 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-2007 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-2007 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-2007 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        #   GNU/Linux
2712        *:Linux:* )
2713            #   determine architecture
2714            AT="${UNAME_MACHINE}"
2715            case "${AT}" in
2716               ia64     ) AT="IA64"   ;;
2717               x86_64   ) AT='AMD64'  ;;
2718               parisc   ) AT="HPPA32" ;;
2719               parisc64 ) AT="HPPA64" ;;
2720            esac
2721            AP="${AT}"
2722            case "${AP}" in
2723               i[3-6]86 ) AP='iX86' ;;
2724            esac
2725            AC="${AP}"
2726            #   determine system
2727            v_kern=`echo "${UNAME_RELEASE}" |\
2728                sed -e 's/^\([0-9][0-9]*\.[0-9][0-9]*\).*/\1/'`
2729            v_libc=`(strings /lib/libc.so.* | grep '^GLIBC_' | sed -e 's/^GLIBC_//' |\
2730                env -i sort -n | sed -n -e '$p' | sed -e 's/^\([0-9][0-9]*\.[0-9][0-9]*\).*/\1/') 2>/dev/null`
2731            ST="GNU/<Linux >${v_libc}/<${v_kern}>"
2732            if [ -f /etc/lsb-release ]; then
2733                eval `( . /etc/lsb-release
2734                    echo "SC=\"LSB${LSB_VERSION}\""
2735                    if [ ".${DISTRIB_ID}" != . -a ".${DISTRIB_RELEASE}" != . ]; then
2736                        echo "SP=\"${DISTRIB_ID} ${DISTRIB_RELEASE}\""
2737                    fi
2738                ) 2>/dev/null`
2739            fi
2740            if [ ".$SP" = . ]; then
2741                for tagfile in x \
2742                    `cd /etc && \
2743                    /bin/ls *[_-]release *[_-]version 2>/dev/null | env -i sort | \
2744                    sed -e '/^redhat-release$/d' -e '/^lsb-release$/d'; \
2745                    echo redhat-release lsb-release`
2746                do
2747                    [ ".${tagfile}" = .x ] && continue
2748                    [ ! -f "/etc/${tagfile}" ] && continue
2749                    n=`echo ${tagfile} | sed -e 's/[_-]release$//' -e 's/[_-]version$//'`
2750                    v=`(grep VERSION /etc/${tagfile}; cat /etc/${tagfile}) | grep '[0-9]' | sed -e 'q' |\
2751                       sed -e 's/^/#/' \
2752                           -e 's/^#[^0-9]*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*$/\1/' \
2753                           -e 's/^#[^0-9]*\([0-9][0-9]*\.[0-9][0-9]*\).*$/\1/' \
2754                           -e 's/^#[^0-9]*\([0-9][0-9]*\).*$/\1/' \
2755                           -e 's/^#.*$//'`
2756                    case "`util_lower ${n}`" in
2757                        redhat )
2758                            if [ ".`grep 'Red Hat Enterprise Linux' /etc/${tagfile}`" != . ]; then
2759                                n="<R>ed <H>at <E>nterprise <L>inux"
2760                            else
2761                                n="<R>ed <H>at <L>inux"
2762                            fi
2763                            ;;
2764                        debian             ) n="Debian[ GNU/Linux]"        ;;
2765                        ubuntu             ) n="Ubuntu[ GNU/Linux]"        ;;
2766                        fedora             ) n="<Fedora> Core[ GNU/Linux]" ;;
2767                        suse               ) n="SuSE[ Linux]"              ;;
2768                        mandrake*|mandriva ) n="Mandriva[ Linux]"          ;;
2769                        gentoo             ) n="Gentoo[ GNU/Linux]"        ;;
2770                        slackware          ) n="Slackware[ Linux]"         ;;
2771                        turbolinux         ) n="TurboLinux"                ;;
2772                        unitedlinux        ) n="UnitedLinux"               ;;
2773                        *                  ) n="${n}[ GNU/Linux]"          ;;
2774                    esac
2775                    case "$n" in
2776                        *"<"*">"* ) SP="$n <$v>" ;;
2777                        *         ) SP="$n $v"   ;;
2778                    esac
2779                    break
2780                done
2781            fi
2782            [ ".$SP" = . ] && SP="${ST}"
2783            [ ".$SC" = . ] && SC="LSB"
2784            ;;
2785
2786        #   Sun Solaris
2787        *:SunOS:* )
2788            #   determine architecture
2789            AT="${UNAME_MACHINE}"
2790            case "${AT}" in
2791                i86pc )
2792                    AT="iX86"
2793                    case "`(/bin/isainfo -k) 2>&1`" in
2794                        amd64 ) AT="AMD64" ;;
2795                    esac
2796                    ;;
2797            esac
2798            AP="${AT}"
2799            case "${AP}" in
2800                sun4[cdm] ) AP="SPARC32" ;;
2801                sun4[uv]  ) AP="SPARC64" ;;
2802                sun4*     ) AP="SPARC"   ;;
2803            esac
2804            AC="${AP}"
2805            case "${AC}" in
2806                SPARC* ) AC="SPARC" ;;
2807            esac
2808            #   determine system
2809            ST="[Sun ]SunOS ${UNAME_RELEASE}"
2810            v=`echo "${UNAME_RELEASE}" |\
2811               sed -e 's;^4\.;1.;' \
2812                   -e 's;^5\.\([0-6]\)[^0-9]*$;2.\1;' \
2813                   -e 's;^5\.\([0-9][0-9]*\).*;\1;'`
2814            SP="[Sun ]Solaris $v"
2815            case "${UNAME_RELEASE}" in
2816                4.* ) SC="4.3BSD" ;;
2817                5.* ) SC="SVR4"   ;;
2818            esac
2819            ;;
2820
2821        #   SCO UnixWare
2822        *:UnixWare:* )
2823            #   determine architecture
2824            AT="${UNAME_MACHINE}"
2825            case "${AT}" in
2826                i[3-6]86 | ix86at ) AT="iX86" ;;
2827            esac
2828            AP="${AT}"
2829            #   determine system
2830            v=`/sbin/uname -v`
2831            ST="[SCO ]UnixWare ${v}"
2832            SP="${ST}"
2833            SC="SVR${UNAME_RELEASE}"
2834            ;;
2835
2836        #   QNX
2837        *:QNX:* )
2838            #   determine architecture
2839            AT="${UNAME_MACHINE}"
2840            case "${AT}" in
2841                x86pc ) AT="iX86" ;;
2842            esac
2843            AP="${AT}"
2844            #   determine system
2845            v="${UNAME_RELEASE}"
2846            ST="QNX[ Neutrino RTOS] ${v}"
2847            v=`echo "${v}" | sed -e 's;^\([0-9][0-9]*\.[0-9][0-9]*\).*$;\1;'`
2848            SP="QNX[ Neutrino RTOS] ${v}"
2849            SC="QNX"
2850            ;;
2851
2852        #   SGI IRIX
2853        *:IRIX*:* )
2854            #   determine architecture
2855            AT="${UNAME_MACHINE}"
2856            AP="${AT}"
2857            case "${AP}:${UNAME_SYSTEM}" in
2858                IP*:IRIX64 ) AP="MIPS64" ;;
2859                IP*:*      ) AP="MIPS"   ;;
2860            esac
2861            AC="${AP}"
2862            #   determine system
2863            v=`(/bin/uname -R || /bin/uname -r) 2>/dev/null | sed -e 's;[0-9.]* ;;'`
2864            ST="[SGI ]IRIX ${v}"
2865            v="${UNAME_RELEASE}"
2866            SP="[SGI ]IRIX ${v}"
2867            SC="4.2BSD/SVR3"
2868            ;;
2869
2870        #   HP HP-UX
2871        *:HP-UX:* )
2872            #   determine architecture
2873            AT="${UNAME_MACHINE}"
2874            case "${AT}" in
2875                ia64 ) AT="IA64" ;;
2876                9000/[34]?? ) AT=M68K ;;
2877                9000/[678][0-9][0-9])
2878                    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
2879                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
2880                    case "${sc_cpu_version}" in
2881                        523 ) AT="HPPA1.0" ;;
2882                        528 ) AT="HPPA1.1" ;;
2883                        532 ) AT="HPPA2.0"
2884                            case "${sc_kernel_bits}" in
2885                                32 ) AT="${AT}n" ;;
2886                                64 ) AT="${AT}w" ;;
2887                            esac
2888                            ;;
2889                    esac
2890                    ;;
2891            esac
2892            AP="${AT}"
2893            case "${AP}" in
2894                HPPA* ) AP="HPPA" ;;
2895            esac
2896            AC="${AP}"
2897            #   determine system
2898            v=`echo "${UNAME_RELEASE}" | sed -e 's;^[^0-9]*;;'`
2899            ST="[HP ]<HP>-<UX ${v}>"
2900            SP="${ST}"
2901            case "${v}" in
2902                10.*   ) SC="SVR4.2" ;;
2903                [7-9]* ) SC="SVR4"   ;;
2904            esac
2905            ;;
2906
2907        #   HP Tru64 (OSF1)
2908        *:OSF1:* )
2909            #   determine architecture
2910            AP="${UNAME_MACHINE}"
2911            case "${AP}" in
2912                alpha ) AP="Alpha" ;;
2913            esac
2914            alpha_type=`(/usr/sbin/psrinfo -v) 2>/dev/null |\
2915                sed -n -e 's/^.*The alpha \([^ ][^ ]*\).*processor.*$/\1/p' | sed -e 'q'`
2916            AT="${AP}${alpha_type}"
2917            AC="${AP}"
2918            #   determine system
2919            v=`echo "${UNAME_RELEASE}" | sed -e 's;^[VTX];;'`
2920            ST="[HP ]Tru64 ${v}"
2921            SP="${ST}"
2922            SC="OSF1"
2923            ;;
2924
2925        #   IBM AIX
2926        *:AIX:* )
2927            cpu_arch=rs6000
2928            if [ -x /usr/sbin/lsdev -a -x /usr/sbin/lsattr ]; then
2929                cpu_id=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
2930                if [ ".`/usr/sbin/lsattr -El ${cpu_id} | grep -i powerpc`" != . ]; then
2931                    cpu_arch=powerpc
2932                fi
2933            elif [ -d /QOpenSys ]; then
2934                #   IBM i5/OS (aka OS/400) with PASE (Portable Application Solutions Environment)
2935                cpu_arch=powerpc
2936            fi
2937            if [ -x /usr/bin/oslevel ]; then
2938                os_level=`/usr/bin/oslevel`
2939            else
2940                os_level="`uname -v`.`uname -r`"
2941            fi
2942            os_level=`echo "${os_level}" |\
2943                      sed -e 's;^\([0-9][0-9]*\.[0-9][0-9]*\)\(\.[0-9][0-9]*\)\(.*\)$;<\1>\2[\3];' \
2944                          -e 's;^\([0-9][0-9]*\.[0-9][0-9]*\)\(.*\)$;<\1>\2;'`
2945            AT="${cpu_arch}"
2946            AP="${AT}"
2947            AC="${AP}"
2948            ST="[IBM ]<AIX >${os_level}"
2949            SP="${ST}"
2950            case "${os_level}" in
2951                [12]* ) SC="SVR2" ;;
2952                *     ) SC="SVR4" ;;
2953            esac
2954            ;;
2955
2956        #   Apple MacOS X Darwin
2957        *:Darwin:* )
2958            AT=`uname -p`
2959            case "${AT}" in
2960                powerpc ) AT="PPC" ;;
2961            esac
2962            AP="${AT}"
2963            AC="${AP}"
2964            case "${AC}" in
2965                i?86 ) AC="iX86" ;;
2966            esac
2967            ST="[Apple ]${UNAME_SYSTEM} ${UNAME_RELEASE}"
2968            SP="${ST}"
2969            SC="4.4BSD/Mach3"
2970            ;;
2971
2972        #   TODO ...ADD YOUR NEW PLATFORM CHECK HERE... TODO
2973        # *:XXX:* )
2974        #   ...
2975        #   ;;
2976
2977        #   ...A STILL UNKNOWN PLATFORM...
2978        * )
2979            AT=`echo "${UNAME_MACHINE}" | sed -e "s; ;${opt_C};g"`
2980            AP="${AT}"
2981            AC="${AP}"
2982            v=`echo "${UNAME_RELEASE}" |\
2983               sed -e 's/^/#/' \
2984                   -e 's/^#[^0-9]*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*$/\1/' \
2985                   -e 's/^#[^0-9]*\([0-9][0-9]*\.[0-9][0-9]*\).*$/\1/' \
2986                   -e 's/^#[^0-9]*\([0-9][0-9]*\).*$/\1/' \
2987                   -e 's/^#.*$/?/'`
2988            ST="${UNAME_SYSTEM} ${v}"
2989            SP="${ST}"
2990            SC="${SP}"
2991            ;;
2992
2993    esac
2994
2995    #   provide fallback values
2996    [ ".$AT" = . ] && AT="${AP:-${AC}}"
2997    [ ".$AP" = . ] && AP="${AT:-${AC}}"
2998    [ ".$AC" = . ] && AC="${AP:-${AT}}"
2999    [ ".$ST" = . ] && ST="${SP:-${SC}}"
3000    [ ".$SP" = . ] && SP="${ST:-${SC}}"
3001    [ ".$SC" = . ] && SC="${SP:-${ST}}"
3002
3003    #   support explicit enforced verbose/concise output
3004    if [ ".$opt_v" = .yes ]; then
3005        opt_F=`echo ":$opt_F" | sed -e 's/^://' -e 's/%\([as][cpt]\)/%[\1]/g'`
3006    elif [ ".$opt_c" = .yes ]; then
3007        opt_F=`echo ":$opt_F" | sed -e 's/^://' -e 's/%\([as][cpt]\)/%<\1>/g'`
3008    fi
3009
3010    #   provide verbose and concise variants
3011    AC_V=""; AC_N=""; AC_C=""
3012    AP_V=""; AP_N=""; AP_C=""
3013    AT_V=""; AT_N=""; AT_C=""
3014    SC_V=""; SC_N=""; SC_C=""
3015    SP_V=""; SP_N=""; SP_C=""
3016    ST_V=""; ST_N=""; ST_C=""
3017    for var_lc in at ap ac st sp sc; do
3018        case "$opt_F" in
3019            *"%[${val_lc}]"* | *"%{${val_lc}}"* | *"%${val_lc}"* | *"%<${val_lc}>"* )
3020            var_uc=`util_upper "$var_lc"`
3021            eval "val=\"\$${var_uc}\""
3022            val_V=""; val_N=""; val_C=""
3023            case "$opt_F" in
3024                *"%[${var_lc}]"* )
3025                    val_V=`echo ":$val" | \
3026                           sed -e 's/^://' \
3027                               -e 's;\[\([^]]*\)\];\1;g' \
3028                               -e 's;<\([^>]*\)>;\1;g' \
3029                               -e "s; ;��;g" \
3030                               -e "s;/;%%;g" \
3031                               -e "s;��;${opt_S};g" \
3032                               -e "s;%%;${opt_C};g"`
3033                    eval "${var_uc}_V=\"\${val_V}\""
3034                    ;;
3035            esac
3036            case "$opt_F" in
3037                *"%{${var_lc}}"* | *"%${var_lc}"* )
3038                    val_N=`echo ":$val" | \
3039                           sed -e 's/^://' \
3040                               -e 's;\[\([^]]*\)\];;g' \
3041                               -e 's;<\([^>]*\)>;\1;g' \
3042                               -e "s; ;��;g" \
3043                               -e "s;/;%%;g" \
3044                               -e "s;��;${opt_S};g" \
3045                               -e "s;%%;${opt_C};g"`
3046                    eval "${var_uc}_N=\"\${val_N}\""
3047                    ;;
3048            esac
3049            case "$opt_F" in
3050                *"%<${var_lc}>"* )
3051                    val_C=`echo ":$val" | \
3052                           sed -e 's/^://' \
3053                               -e 's;\[\([^]]*\)\];;g' \
3054                               -e 's;[^<]*<\([^>]*\)>[^<]*;\1;g' \
3055                               -e "s; ;��;g" \
3056                               -e "s;/;%%;g" \
3057                               -e "s;��;${opt_S};g" \
3058                               -e "s;%%;${opt_C};g"`
3059                    eval "${var_uc}_C=\"\${val_C}\""
3060                    ;;
3061            esac
3062            ;;
3063        esac
3064    done
3065
3066    #   create output string
3067    output=`echo ":$opt_F" |\
3068            sed -e "s/^://" \
3069                -e "s;%\\[ac\\];${AC_V};g" \
3070                -e "s;%{ac};${AC_N};g" \
3071                -e "s;%ac;${AC_N};g" \
3072                -e "s;%<ac>;${AC_C};g" \
3073                -e "s;%\\[ap\\];${AP_V};g" \
3074                -e "s;%{ap};${AP_N};g" \
3075                -e "s;%ap;${AP_N};g" \
3076                -e "s;%<ap>;${AP_C};g" \
3077                -e "s;%\\[at\\];${AT_V};g" \
3078                -e "s;%{at};${AT_N};g" \
3079                -e "s;%at;${AT_N};g" \
3080                -e "s;%<at>;${AT_C};g" \
3081                -e "s;%\\[sc\\];${SC_V};g" \
3082                -e "s;%{sc};${SC_N};g" \
3083                -e "s;%sc;${SC_N};g" \
3084                -e "s;%<sc>;${SC_C};g" \
3085                -e "s;%\\[sp\\];${SP_V};g" \
3086                -e "s;%{sp};${SP_N};g" \
3087                -e "s;%sp;${SP_N};g" \
3088                -e "s;%<sp>;${SP_C};g" \
3089                -e "s;%\\[st\\];${ST_V};g" \
3090                -e "s;%{st};${ST_N};g" \
3091                -e "s;%st;${ST_N};g" \
3092                -e "s;%<st>;${ST_C};g" \
3093                -e 's/\\\\n/^/g' |\
3094             tr '^' '\012'`
3095
3096    #   support lower/upper-case mapping
3097    if [ ".$opt_L" = .yes ]; then
3098        output=`util_lower "$output"`
3099    elif [ ".$opt_U" = .yes ]; then
3100        output=`util_upper "$output"`
3101    fi
3102
3103    #   display output string
3104    if [ ".$opt_n" = .yes ]; then
3105        echo . | awk '{ printf("%s", output); }' output="$output"
3106    else
3107        echo "$output"
3108    fi
3109
3110    shtool_exit 0
3111    ;;
3112
3113arx )
3114    ##
3115    ##  arx -- Extended archive command
3116    ##  Copyright (c) 1999-2007 Ralf S. Engelschall <rse@engelschall.com>
3117    ##
3118
3119    ar_prg="$opt_C"
3120    ar_cmd="$1"; shift
3121    archive="$1"; shift
3122    files="$*"
3123
3124    #   walk through the file list and expand archives members
3125    ar_tmpdir=`echo $archive | sed -e 's;[^/]*$;.arx;'`
3126    nfiles=''
3127    if [ ".$files" != . ]; then
3128        for file in $files; do
3129            if [ ! -f $file ]; then
3130                echo "$msgprefix:Error: input file not found: $file" 1>&2
3131                shtool_exit 1
3132            fi
3133            case $file in
3134                *.a )
3135                    if [ ! -d $ar_tmpdir ]; then
3136                        if [ ".$opt_t" = .yes ]; then
3137                            echo "mkdir $ar_tmpdir" 1>&2
3138                        fi
3139                        mkdir $ar_tmpdir
3140                    fi
3141                    case $ar_tmpdir in
3142                         .arx )
3143                             from="../$file"
3144                             ;;
3145                         * )
3146                             dir=`echo $file | sed -e 's;[^/]*$;;' -e 's;\(.\)/$;\1;' -e 's;^$;.;'`
3147                             base=`echo $file | sed -e 's;.*/\([^/]*\)$;\1;'`
3148                             from="`cd $dir; pwd`/$base"
3149                             ;;
3150                    esac
3151                    if [ ".$opt_t" = .yes ]; then
3152                        echo "(cd $ar_tmpdir && $ar_prg x $from)" 1>&2
3153                    fi
3154                    (cd $ar_tmpdir && eval $ar_prg x $from)
3155                    if [ $? -ne 0 ]; then
3156                        echo "$msgprefix:Error: member extraction failed for archive: $file" 1>&2
3157                        shtool_exit 1
3158                    fi
3159                    for member in - `eval $ar_prg t $file | sed -e '/_\.SYMDEF/d'`; do
3160                        [ ".$member" = .- ] && continue
3161                        nfiles="$nfiles $ar_tmpdir/$member"
3162                    done
3163                    ;;
3164                * )
3165                    nfiles="$nfiles $file"
3166                    ;;
3167            esac
3168        done
3169    fi
3170
3171    #   run the final archive command
3172    if [ ".$opt_t" = .yes ]; then
3173        echo "$ar_prg $ar_cmd $archive $nfiles" 1>&2
3174    fi
3175    eval $ar_prg $ar_cmd $archive $nfiles
3176    if [ $? -ne 0 ]; then
3177        echo "$msgprefix:Error: archive command failed" 1>&2
3178        shtool_exit $?
3179    fi
3180
3181    #   cleanup and die gracefully
3182    if [ -d $ar_tmpdir ]; then
3183        if [ ".$opt_t" = .yes ]; then
3184            echo "rm -rf $ar_tmpdir" 1>&2
3185        fi
3186        rm -rf $ar_tmpdir
3187    fi
3188
3189    shtool_exit 0
3190    ;;
3191
3192slo )
3193    ##
3194    ##  slo -- Separate linker options by library class
3195    ##  Copyright (c) 1998-2007 Ralf S. Engelschall <rse@engelschall.com>
3196    ##
3197
3198    DIFS="$IFS"
3199
3200    #   parse out -L and -l options from command line
3201    DIRS=''
3202    LIBS=''
3203    ARGV=''
3204    optprev=''
3205    for opt
3206    do
3207        #   concatenate with previous option if exists
3208        if [ ".$optprev" != . ]; then
3209            opt="${optprev}${opt}";
3210            optprev=''
3211        fi
3212        #   remember options for arg if used stand-alone
3213        if [ ".$opt" = ".-L" ] || [ ".$opt" = ".-l" ]; then
3214            optprev="$opt"
3215            continue;
3216        fi
3217        #   split argument into option plus option argument
3218        arg="`echo $opt | cut -c3-`"
3219        opt="`echo $opt | cut -c1-2`"
3220        #   store into containers
3221        case $opt in
3222            -L) DIRS="$DIRS:$arg" ;;
3223            -l) LIBS="$LIBS:$arg" ;;
3224             *) ARGV="$ARGV $opt" ;;
3225        esac
3226    done
3227
3228    #   set linker default directories
3229    DIRS_DEFAULT='/lib:/usr/lib'
3230    if [ ".$LD_LIBRARY_PATH" != . ]; then
3231        DIRS_DEFAULT="$DIRS_DEFAULT:$LD_LIBRARY_PATH"
3232    fi
3233
3234    #   sort options by class
3235    DIRS_OBJ=''
3236    LIBS_OBJ=''
3237    DIRS_PIC=''
3238    LIBS_PIC=''
3239    DIRS_DSO=''
3240    LIBS_DSO=''
3241
3242    #    for each library...
3243    OIFS="$IFS"; IFS=':'
3244    for lib in $LIBS; do
3245        [ ".$lib" = . ] && continue
3246
3247        found='no'
3248        found_indefdir='no'
3249        found_type=''
3250        found_dir=''
3251
3252        #    for each directory...
3253        OIFS2="$IFS"; IFS=":$DIFS"
3254        for dir in ${DIRS} switch-to-defdirs ${DIRS_DEFAULT}; do
3255            [ ".$dir" = . ] && continue
3256            [ ".$dir" = .switch-to-defdirs ] && found_indefdir=yes
3257            [ ! -d $dir ] && continue
3258
3259            #    search the file
3260            OIFS3="$IFS"; IFS="$DIFS"
3261            for file in '' `cd $dir && env -i /bin/ls lib${lib}.* 2>/dev/null`; do
3262                 [ ".$file" = . ] && continue
3263                 case $file in
3264                     *.so|*.so.[0-9]*|*.sl|*.sl.[0-9]* )
3265                          found=yes;
3266                          found_type=DSO;
3267                          break
3268                          ;;
3269                     *.lo|*.la )
3270                          found=yes;
3271                          found_type=PIC
3272                          ;;
3273                     *.a )
3274                          if [ ".$found_type" = . ]; then
3275                              found=yes
3276                              found_type=OBJ
3277                          fi
3278                          ;;
3279                 esac
3280            done
3281            IFS="$OIFS3"
3282            if [ ".$found" = .yes ]; then
3283                found_dir="$dir"
3284                break
3285            fi
3286        done
3287        IFS="$OIFS2"
3288
3289        if [ ".$found" = .yes ]; then
3290            if [ ".$found_indefdir" != .yes ]; then
3291                eval "dirlist=\"\${DIRS_${found_type}}:\""
3292                case "$dirlist" in
3293                    *:$found_dir:* ) ;;
3294                    * ) eval "DIRS_${found_type}=\"\$DIRS_${found_type}:${found_dir}\"" ;;
3295                esac
3296                eval "LIBS_${found_type}=\"\$LIBS_${found_type}:$lib\""
3297            else
3298                eval "LIBS_${found_type}=\"\$LIBS_${found_type}:$lib\""
3299            fi
3300        else
3301            LIBS_OBJ="$LIBS_OBJ:$lib"
3302            #dirlist="`echo $DIRS $DIRS_DEFAULT | sed -e 's/:/ /g'`"
3303            #echo "slo:Warning: library \"$lib\" not found in any of the following dirs:" 2>&1
3304            #echo "slo:Warning: $dirlist" 1>&1
3305        fi
3306    done
3307    IFS="$OIFS"
3308
3309    #   also pass-through unused dirs even if it's useless
3310    OIFS="$IFS"; IFS=':'
3311    for dir in $DIRS; do
3312        dirlist="${DIRS_OBJ}:${DIRS_PIC}:${DIRS_DSO}:"
3313        case "$dirlist" in
3314            *:$dir:* ) ;;
3315            * ) DIRS_OBJ="$DIRS_OBJ:$dir" ;;
3316        esac
3317    done
3318    IFS="$OIFS"
3319
3320    #   reassemble the options but separated by type
3321    for type in OBJ PIC DSO; do
3322        OIFS="$IFS"; IFS=':'
3323        eval "libs=\"\$LIBS_${type}\""
3324        opts=''
3325        for lib in $libs; do
3326            [ ".$lib" = . ] && continue
3327            opts="$opts -l$lib"
3328        done
3329        eval "LIBS_${type}=\"$opts\""
3330
3331        eval "dirs=\"\$DIRS_${type}\""
3332        opts=''
3333        for dir in $dirs; do
3334            [ ".$dir" = . ] && continue
3335            opts="$opts -L$dir"
3336        done
3337        eval "DIRS_${type}=\"$opts\""
3338        IFS="$OIFS"
3339    done
3340
3341    #   give back results
3342    for var in ARGV DIRS_OBJ LIBS_OBJ DIRS_PIC LIBS_PIC DIRS_DSO LIBS_DSO; do
3343        eval "val=\"\$${var}\""
3344        val="`echo $val | sed -e 's/^ *//'`"
3345        echo "${opt_p}${var}=\"${val}\""
3346    done
3347
3348    shtool_exit 0
3349    ;;
3350
3351scpp )
3352    ##
3353    ##  scpp -- Sharing C Pre-Processor
3354    ##  Copyright (c) 1999-2007 Ralf S. Engelschall <rse@engelschall.com>
3355    ##
3356
3357    srcs="$*"
3358    output="${opt_o}.n"
3359
3360    #   find a reasonable Awk
3361    awk=''
3362    paths=`echo $PATH |\
3363           sed -e 's%/*:%:%g' -e 's%/$%%' \
3364               -e 's/^:/.:/' -e 's/::/:.:/g' -e 's/:$/:./' \
3365               -e 's/:/ /g'`
3366    for name in gawk nawk awk; do
3367        for path in $paths; do
3368            if [ -r "$path/$name" ]; then
3369                awk="$path/$name"
3370                break
3371            fi
3372        done
3373        if [ ".$awk" != . ]; then
3374            break
3375        fi
3376    done
3377    if [ ".$awk" = . ]; then
3378        echo "$msgprefix:Error: cannot find a reasonable Awk" 1>&2
3379        shtool_exit 1
3380    fi
3381
3382    #   parse source file(s)
3383    if [ ".$opt_v" = .yes ]; then
3384        echo "Parsing:" | $awk '{ printf("%s", $0); }' 1>&2
3385    fi
3386    for src in $srcs; do
3387        if [ ".$opt_v" = .yes ]; then
3388            echo $src | $awk '{ printf(" %s", $0); }' 1>&2
3389        fi
3390        if [ ".$opt_f" != . ]; then
3391            inputcmd="sed"
3392            OIFS="$IFS"; IFS="$ASC_NL"; set -- $opt_f; IFS="$OIFS"
3393            for e
3394            do
3395                inputcmd="$inputcmd -e '$e'"
3396            done
3397            inputcmd="$inputcmd '$src'"
3398        else
3399            inputcmd="cat '$src'"
3400        fi
3401        eval $inputcmd |\
3402        $awk '
3403           BEGIN {
3404               ln    = 0;
3405               fln   = 0;
3406               level = 0;
3407               mode  = "";
3408               store = "";
3409           }
3410           {
3411               ln++;
3412           }
3413           /^#if.*/ {
3414               level++;
3415           }
3416           /^#if [a-zA-Z_][a-zA-Z0-9_]* *$/ {
3417               if ($2 == define) {
3418                   mode = "D";
3419                   printf("D:#line %d \"%s\"\n", ln, src);
3420                   next;
3421               }
3422           }
3423           /^#endif.*/ {
3424               level--;
3425               if (mode == "D" && level == 0) {
3426                   mode = "";
3427                   next;
3428               }
3429           }
3430           /^[a-zA-Z_][a-zA-Z0-9_].*;.*/ {
3431               if ($1 == class) {
3432                   printf("V:#line %d \"%s\"\n", ln, src);
3433                   printf("V:%s\n", $0);
3434                   printf("J:%s\n", $0);
3435                   next;
3436               }
3437           }
3438           /^[a-zA-Z_][a-zA-Z0-9_].*=.*/ {
3439               if ($1 == class) {
3440                   printf("V:#line %d \"%s\"\n", ln, src);
3441                   printf("V:%s\n", $0);
3442                   printf("J:%s\n", $0);
3443                   next;
3444               }
3445           }
3446           /^[a-zA-Z_][a-zA-Z0-9_]*/ {
3447               if ($1 == class) {
3448                   fln = ln;
3449                   store = $0;
3450                   mode = "F";
3451                   next;
3452               }
3453           }
3454           /^\{ *$/ {
3455               if (mode == "F") {
3456                   printf("F:#line %d \"%s\"\n", fln, src);
3457                   printf("F:%s;\n", store);
3458                   printf("I:%s;\n", store);
3459                   store = "";
3460                   mode = "";
3461                   next;
3462               }
3463           }
3464           {
3465               if (mode == "D")
3466                   printf("D:%s\n", $0);
3467               else if (mode == "F")
3468                   store = store " " $0;
3469           }
3470        ' "src=$src" "define=$opt_D" "class=$opt_C" >>$tmpfile
3471    done
3472    if [ ".$opt_v" = .yes ]; then
3473        echo "" 1>&2
3474    fi
3475
3476    #   start generating output header
3477    echo "/* $opt_o -- autogenerated from $opt_t, DO NOT EDIT! */" >$output
3478    echo "#line 1 \"$opt_t\"" >>$output
3479    sed <$opt_t -e "1,/^${opt_M} *\$/p" -e 'd' |\
3480    sed -e "/^${opt_M} *\$/d" >>$output
3481
3482    #   merge in the define blocks
3483    grep '^D:' $tmpfile | sed -e 's/^D://' >>$output
3484
3485    #   generate standard prolog
3486    echo "#line 1 \"_ON_THE_FLY_\"" >>$output
3487    echo "" >>$output
3488    echo "/* make sure the scpp source extensions are skipped */" >>$output
3489    echo "#define $opt_D 0" >>$output
3490    echo "#define $opt_C /**/" >>$output
3491
3492    #   generate namespace hiding for variables
3493    echo "" >>$output
3494    echo "/* move intern variables to hidden namespace */" >>$output
3495    grep '^J:' $tmpfile | sed >>$output \
3496        -e 's/^J://' \
3497        -e 's/  */ /g' \
3498        -e 's/^[^=;]*[ *]\([a-zA-Z0-9_]*\)\[\];.*$/#define \1 __\1/' \
3499        -e 's/^[^=;]*[ *]\([a-zA-Z0-9_]*\)\[\] =.*$/#define \1 __\1/' \
3500        -e 's/^[^=;]*[ *]\([a-zA-Z0-9_]*\);.*$/#define \1 __\1/' \
3501        -e 's/^[^=;]*[ *]\([a-zA-Z0-9_]*\) =.*$/#define \1 __\1/'
3502
3503    #   generate namespace hiding for functions
3504    echo "" >>$output
3505    echo "/* move intern functions to hidden namespace */" >>$output
3506    grep '^I:' $tmpfile | sed >>$output \
3507        -e 's/^I://' \
3508        -e 's/\([ (]\) */\1/g' \
3509        -e 's/ *\([),]\)/\1/g' \
3510        -e 's/^[^(]*[ *]\([a-zA-Z0-9_]*\)(.*$/#define \1 __\1/'
3511
3512    #   generate prototypes for variables
3513    echo "" >>$output
3514    echo "/* prototypes for intern variables */" >>$output
3515    grep '^V:' $tmpfile | sed >>$output \
3516        -e 's/^V://' \
3517        -e 's/  */ /g' \
3518        -e 's/^\([^=;]*[ *][a-zA-Z0-9_]*\[\]\);.*$/\1;/' \
3519        -e 's/^\([^=;]*[ *][a-zA-Z0-9_]*\[\]\) =.*$/\1;/' \
3520        -e 's/^\([^=;]*[ *][a-zA-Z0-9_]*\);.*$/\1;/' \
3521        -e 's/^\([^=;]*[ *][a-zA-Z0-9_]*\) =.*$/\1;/' \
3522        -e 's/ ;/;/g' \
3523        -e "s/^$opt_C /extern /"
3524
3525    #   generate prototypes for functions
3526    echo "" >>$output
3527    echo "/* prototypes for intern functions */" >>$output
3528    grep '^F:' $tmpfile | sed >>$output \
3529        -e 's/^F://' \
3530        -e 's/\([ (]\) */\1/g' \
3531        -e 's/ *\([),]\)/\1/g' \
3532        -e 's/\([* ]\)[a-zA-Z0-9_]*,/\1,/g' \
3533        -e 's/\([* ]\)[a-zA-Z0-9_]*);/\1);/g' \
3534        -e 's/(\*[a-zA-Z0-9_]*)(/(*)(/g' \
3535        -e 's/\([ (]\) */\1/g' \
3536        -e 's/ *\([),]\)/\1/g' \
3537        -e "s/^$opt_C /extern /"
3538
3539    #   finish generating output header
3540    n=`(echo ''; sed <$opt_t -e "1,/^${opt_M} *\$/p" -e 'd') |\
3541       wc -l | sed -e 's;^ *\([0-9]*\) *$;\1;'`
3542    echo "#line $n \"$opt_t\"" >>$output
3543    sed <$opt_t -e "/^${opt_M} *\$/,\$p" -e 'd' |\
3544    sed -e "/^${opt_M} *\$/d" >>$output
3545
3546    #   create final output file
3547    if [ -f $opt_o ]; then
3548        if [ ".$opt_p" = .yes ]; then
3549            grep -v '^#line' $opt_o  >$tmpfile.o
3550            grep -v '^#line' $output >$tmpfile.n
3551            out_old="$tmpfile.o"
3552            out_new="$tmpfile.n"
3553        else
3554            out_old="$opt_o"
3555            out_new="$output"
3556        fi
3557        if cmp -s $out_old $out_new; then
3558            :
3559        else
3560            cp $output $opt_o
3561        fi
3562    else
3563        cp $output $opt_o
3564    fi
3565    rm -f $output
3566    rm -f $tmpfile $tmpfile.* >/dev/null 2>&1
3567
3568    shtool_exit 0
3569    ;;
3570
3571version )
3572    ##
3573    ##  version -- Maintain a version information file
3574    ##  Copyright (c) 1994-2007 Ralf S. Engelschall <rse@engelschall.com>
3575    ##
3576
3577    file="$1"
3578
3579    #   determine prefix and name
3580    name="$opt_n"
3581    prefix="$opt_p"
3582
3583    #   determine current version
3584    triple="$opt_s"
3585    if [ ".$triple" != . ]; then
3586        #   use given triple
3587        if [ ".`echo $triple | grep '[0-9]*.[0-9]*[sabp.][0-9]*'`" = . ]; then
3588            echo "$msgprefix:Error: invalid argument to option \`-s': \`$opt_s'" 1>&2
3589            shtool_exit 1
3590        fi
3591        eval `echo $triple |\
3592              sed -e 's%\([0-9]*\)\.\([0-9]*\)\([sabp.]\)\([0-9]*\).*%\
3593              ver="\1";rev="\2";typ="\3";lev="\4"%'`
3594        tim=calc
3595    elif [ -r $file ]; then
3596        #   determine triple from given file
3597        eval `grep 'Version [0-9]*.[0-9]*[sabp.][0-9]* ([0-9]*-[a-zA-Z]*-[0-9]*)' $file |\
3598              sed -e 's%.*Version \([0-9]*\)\.\([0-9]*\)\([sabp.]\)\([0-9]*\) (\([0-9]*-[a-zA-Z]*-[0-9]*\)).*%\
3599              ver="\1";rev="\2";typ="\3";lev="\4";tim="\5"%' -e 'q'`
3600    else
3601        #   intialise to first version
3602        ver=0
3603        rev=1
3604        typ=.
3605        lev=0
3606        tim=calc
3607    fi
3608
3609    #   determine new version in batch
3610    if [ ".$opt_i" != . ]; then
3611        case $opt_i in
3612            v ) ver=`expr $ver + 1`
3613                rev=0
3614                lev=0
3615                ;;
3616            r ) rev=`expr $rev + 1`
3617                lev=0
3618                ;;
3619            l ) lev=`expr $lev + 1`
3620                ;;
3621            * ) echo "$msgprefix:Error: invalid argument to option \`-i': \`$opt_i'" 1>&2
3622                shtool_exit 1
3623                ;;
3624        esac
3625        tim=calc
3626    fi
3627
3628    #   determine new version interactively
3629    if [ ".$opt_e" = .yes ]; then
3630        echo "old version: ${ver}.${rev}${typ}${lev}"
3631        while [ 1 ]; do
3632            echo dummy | awk '{ printf("new version: "); }'
3633            read triple
3634            case $triple in
3635                [0-9]*.[0-9]*[sabp.][0-9]* )
3636                    ;;
3637                * ) echo "$msgprefix:Error: invalid version string entered: \`$triple'" 1>&2
3638                    continue
3639                    ;;
3640            esac
3641            break
3642        done
3643        eval `echo $triple |\
3644              sed -e 's%^\([0-9]*\)\.\([0-9]*\)\([sabp.]\)\([0-9]*\)$%\
3645              ver="\1";rev="\2";typ="\3";lev="\4"%'`
3646        tim=calc
3647    fi
3648
3649    #   determine hexadecimal and libtool value of version
3650    case $typ in
3651        a     ) typnum=0;  levnum=$lev ;;
3652        b     ) typnum=1;  levnum=$lev ;;
3653        p | . ) typnum=2;  levnum=$lev ;;
3654        s     ) typnum=15; levnum=255  ;; # snapshots are special
3655    esac
3656    hex=`echo "$ver:$rev:$typnum:$levnum" |\
3657         awk -F: '{ printf("0x%x%02x%1x%02x", $1, $2, $3, $4); }' |\
3658         tr 'abcdef' 'ABCDEF'`
3659    ltv=`echo "$ver:$rev:$typnum:$levnum" |\
3660         awk -F: '{ printf("%d:%d", $1*10 + $2, $3*10 + $4); }'`
3661
3662    #   determine date
3663    if [ ".$tim" = .calc ]; then
3664        day=`date '+%d'`
3665        month=`date '+%m'`
3666        year=`date '+%Y' 2>/dev/null`
3667        if [ ".$time_year" = . ]; then
3668            year=`date '+%y'`
3669            case $year in
3670                [5-9][0-9]) year="19$year" ;;
3671                [0-4][0-9]) year="20$year" ;;
3672            esac
3673        fi
3674        case $month in
3675            1|01) month='Jan' ;;
3676            2|02) month='Feb' ;;
3677            3|03) month='Mar' ;;
3678            4|04) month='Apr' ;;
3679            5|05) month='May' ;;
3680            6|06) month='Jun' ;;
3681            7|07) month='Jul' ;;
3682            8|08) month='Aug' ;;
3683            9|09) month='Sep' ;;
3684              10) month='Oct' ;;
3685              11) month='Nov' ;;
3686              12) month='Dec' ;;
3687        esac
3688        tim="${day}-${month}-${year}"
3689    fi
3690
3691    #   perform result actions
3692    mode=show
3693    if [ ".$opt_i" != . ]; then
3694        mode=edit
3695    elif [ ".$opt_e" = .yes ]; then
3696        mode=edit
3697    elif [ ".$opt_s" != . ]; then
3698        mode=edit
3699    fi
3700    if [ ".$mode" = .show ]; then
3701        #   just display the current version
3702        case $opt_d in
3703            short )
3704                echo "${ver}.${rev}${typ}${lev}"
3705                ;;
3706            long )
3707                echo "${ver}.${rev}${typ}${lev} ($tim)"
3708                ;;
3709            libtool )
3710                echo "${ltv}"
3711                ;;
3712            hex )
3713                echo "${hex}"
3714                ;;
3715            * ) echo "$msgprefix:Error: invalid argument to option \`-d': \`$opt_d'" 1>&2
3716                shtool_exit 1
3717                ;;
3718        esac
3719    else
3720        #   update the version file
3721
3722        #   pre-generate various strings
3723        triple="${ver}.${rev}${typ}${lev}"
3724        vHex="$hex"
3725        vShort="${triple}"
3726        vLong="${triple} (${tim})"
3727        vTeX="This is ${name}, Version ${triple} (${tim})"
3728        vGNU="${name} ${triple} (${tim})"
3729        vWeb="${name}/${triple}"
3730        vSCCS="@(#)${name} ${triple} (${tim})"
3731        vRCS="\$Id: ${name} ${triple} (${tim}) \$"
3732
3733        #   determine string out of filename
3734        #   (do NOT try to optimize this in any way because of portability)
3735        filestr=`util_upper "$file" | tr './%+' '____' | sed -e 's/-/_/g'`
3736
3737        #   generate uppercase prefix
3738        prefixupper=`util_upper "$prefix"`
3739
3740        #   create the version file according the the selected language
3741        echo "new version: ${vLong}"
3742
3743        cp /dev/null $file
3744        case $opt_l in
3745            txt )
3746                echo >>$file ""
3747                echo >>$file "  ${file} -- Version Information for ${name} (syntax: Text)"
3748                echo >>$file "  [automatically generated and maintained by GNU shtool]"
3749                echo >>$file ""
3750                echo >>$file "  $vTeX"
3751                echo >>$file ""
3752                ;;
3753            c )
3754                echo >>$file "/*"
3755                echo >>$file "**  ${file} -- Version Information for ${name} (syntax: C/C++)"
3756                echo >>$file "**  [automatically generated and maintained by GNU shtool]"
3757                echo >>$file "*/"
3758                echo >>$file ""
3759                echo >>$file "#ifdef _${filestr}_AS_HEADER_"
3760                echo >>$file ""
3761                echo >>$file "#ifndef _${filestr}_"
3762                echo >>$file "#define _${filestr}_"
3763                echo >>$file ""
3764                echo >>$file "#define ${prefixupper}VERSION ${vHex}"
3765                echo >>$file ""
3766                echo >>$file "typedef struct {"
3767                echo >>$file "    const int   v_hex;"
3768                echo >>$file "    const char *v_short;"
3769                echo >>$file "    const char *v_long;"
3770                echo >>$file "    const char *v_tex;"
3771                echo >>$file "    const char *v_gnu;"
3772                echo >>$file "    const char *v_web;"
3773                echo >>$file "    const char *v_sccs;"
3774                echo >>$file "    const char *v_rcs;"
3775                echo >>$file "} ${prefix}version_t;"
3776                echo >>$file ""
3777                echo >>$file "extern ${prefix}version_t ${prefix}version;"
3778                echo >>$file ""
3779                echo >>$file "#endif /* _${filestr}_ */"
3780                echo >>$file ""
3781                echo >>$file "#else /* _${filestr}_AS_HEADER_ */"
3782                echo >>$file ""
3783                echo >>$file "#define _${filestr}_AS_HEADER_"
3784                echo >>$file "#include \"${file}\""
3785                echo >>$file "#undef  _${filestr}_AS_HEADER_"
3786                echo >>$file ""
3787                echo >>$file "${prefix}version_t ${prefix}version = {"
3788                echo >>$file "    ${vHex},"
3789                echo >>$file "    \"${vShort}\","
3790                echo >>$file "    \"${vLong}\","
3791                echo >>$file "    \"${vTeX}\","
3792                echo >>$file "    \"${vGNU}\","
3793                echo >>$file "    \"${vWeb}\","
3794                echo >>$file "    \"${vSCCS}\","
3795                echo >>$file "    \"${vRCS}\""
3796                echo >>$file "};"
3797                echo >>$file ""
3798                echo >>$file "#endif /* _${filestr}_AS_HEADER_ */"
3799                echo >>$file ""
3800                ;;
3801            m4 )
3802                echo >>$file "##"
3803                echo >>$file "##  ${file} -- Version Information for ${name} (syntax: M4)"
3804                echo >>$file "##  [automatically generated and maintained by GNU shtool]"
3805                echo >>$file "##"
3806                echo >>$file ""
3807                echo >>$file "m4_define([v_hex],   [${vHex}])"
3808                echo >>$file "m4_define([v_short], [${vShort}])"
3809                echo >>$file "m4_define([v_long],  [${vLong}])"
3810                echo >>$file "m4_define([v_tex],   [${vTeX}])"
3811                echo >>$file "m4_define([v_gnu],   [${vGNU}])"
3812                echo >>$file "m4_define([v_web],   [${vWeb}])"
3813                echo >>$file "m4_define([v_sccs],  [${vSCCS}])"
3814                echo >>$file "m4_define([v_rcs],   [${vRCS}])"
3815                echo >>$file ""
3816                ;;
3817            perl )
3818                echo >>$file "##"
3819                echo >>$file "##  ${file} -- Version Information for ${name} (syntax: Perl)"
3820                echo >>$file "##  [automatically generated and maintained by GNU shtool]"
3821                echo >>$file "##"
3822                echo >>$file ""
3823                echo >>$file "our \$${prefix}version = {"
3824                echo >>$file "    'v_hex'   => ${vHex},"
3825                echo >>$file "    'v_short' => \"${vShort}\","
3826                echo >>$file "    'v_long'  => \"${vLong}\","
3827                echo >>$file "    'v_tex'   => \"${vTeX}\","
3828                echo >>$file "    'v_gnu'   => \"${vGNU}\","
3829                echo >>$file "    'v_web'   => \"${vWeb}\","
3830                echo >>$file "    'v_sccs'  => \"${vSCCS}\","
3831                echo >>$file "    'v_rcs'   => \"\\${vRCS}/\""
3832                echo >>$file "};"
3833                echo >>$file ""
3834                echo >>$file "1;"
3835                echo >>$file ""
3836                ;;
3837            python )
3838                echo >>$file "##"
3839                echo >>$file "##  ${file} -- Version Information for ${name} (syntax: Python)"
3840                echo >>$file "##  [automatically generated and maintained by GNU shtool]"
3841                echo >>$file "##"
3842                echo >>$file ""
3843                echo >>$file "class ${prefix}version:"
3844                echo >>$file "    v_hex       = ${vHex}"
3845                echo >>$file "    v_short     = \"${vShort}\""
3846                echo >>$file "    v_long      = \"${vLong}\""
3847                echo >>$file "    v_tex       = \"${vTeX}\""
3848                echo >>$file "    v_gnu       = \"${vGNU}\""
3849                echo >>$file "    v_web       = \"${vWeb}\""
3850                echo >>$file "    v_sccs      = \"${vSCCS}\""
3851                echo >>$file "    v_rcs       = \"${vRCS}\""
3852                echo >>$file ""
3853                ;;
3854            * ) echo "$msgprefix:Error: invalid argument to option \`-l': \`$opt_l'" 1>&2
3855                shtool_exit 1
3856                ;;
3857        esac
3858    fi
3859
3860    shtool_exit 0
3861    ;;
3862
3863path )
3864    ##
3865    ##  path -- Deal with program paths
3866    ##  Copyright (c) 1998-2007 Ralf S. Engelschall <rse@engelschall.com>
3867    ##
3868
3869    namelist="$*"
3870
3871    #   check whether the test command supports the -x option
3872    if [ -x /bin/sh ] 2>/dev/null; then
3873        minusx="-x"
3874    else
3875        minusx="-r"
3876    fi
3877
3878    #   split path string
3879    paths="`echo $opt_p |\
3880            sed -e 's/^:/.:/' \
3881                -e 's/::/:.:/g' \
3882                -e 's/:$/:./' \
3883                -e 's/:/ /g'`"
3884
3885    #   SPECIAL REQUEST
3886    #   translate forward to reverse path
3887    if [ ".$opt_r" = .yes ]; then
3888        if [ "x$namelist" = "x." ]; then
3889            rp='.'
3890        else
3891            rp=''
3892            for pe in `IFS="$IFS/"; echo $namelist`; do
3893                rp="../$rp"
3894            done
3895        fi
3896        echo $rp | sed -e 's:/$::'
3897        shtool_exit 0
3898    fi
3899
3900    #   SPECIAL REQUEST
3901    #   strip out directory or base name
3902    if [ ".$opt_d" = .yes ]; then
3903        echo "$namelist" |\
3904        sed -e 's;[^/]*$;;' -e 's;\(.\)/$;\1;'
3905        shtool_exit 0
3906    fi
3907    if [ ".$opt_b" = .yes ]; then
3908        echo "$namelist" |\
3909        sed -e 's;.*/\([^/]*\)$;\1;'
3910        shtool_exit 0
3911    fi
3912
3913    #   MAGIC SITUATION
3914    #   Perl Interpreter (perl)
3915    if [ ".$opt_m" = .yes ] && [ ".$namelist" = .perl ]; then
3916        rm -f $tmpfile >/dev/null 2>&1
3917        touch $tmpfile
3918        found=0
3919        pc=99
3920        for dir in $paths; do
3921            dir=`echo $dir | sed -e 's;/*$;;'`
3922            nc=99
3923            for name in perl perl5 miniperl; do
3924                 if [ $minusx "$dir/$name" ] && [ ! -d "$dir/$name" ]; then
3925                     perl="$dir/$name"
3926                     pv=`$perl -e 'printf("%.3f", $]);'`
3927                     echo "$pv:$pc:$nc:$perl" >>$tmpfile
3928                     found=1
3929                 fi
3930                 nc=`expr $nc - 1`
3931            done
3932            pc=`expr $pc - 1`
3933        done
3934        if [ $found = 1 ]; then
3935            perl="`cat $tmpfile | sort -r -u | sed -e 'q' | cut -d: -f4`"
3936            rm -f $tmpfile >/dev/null 2>&1
3937            echo "$perl"
3938            shtool_exit 0
3939        fi
3940        rm -f $tmpfile >/dev/null 2>&1
3941        shtool_exit 1
3942    fi
3943
3944    #   MAGIC SITUATION
3945    #   C pre-processor (cpp)
3946    if [ ".$opt_m" = .yes ] && [ ".$namelist" = .cpp ]; then
3947        echo >$tmpfile.c "#include <assert.h>"
3948        echo >>$tmpfile.c "Syntax Error"
3949        #   1. try the standard cc -E approach
3950        cpp="${CC-cc} -E"
3951        (eval "$cpp $tmpfile.c >/dev/null") 2>$tmpfile.out
3952        my_error=`grep -v '^ *+' $tmpfile.out`
3953        if [ ".$my_error" != . ]; then
3954            #   2. try the cc -E approach and GCC's -traditional-ccp option
3955            cpp="${CC-cc} -E -traditional-cpp"
3956            (eval "$cpp $tmpfile.c >/dev/null") 2>$tmpfile.out
3957            my_error=`grep -v '^ *+' $tmpfile.out`
3958            if [ ".$my_error" != . ]; then
3959                #   3. try a standalone cpp command in path and lib dirs
3960                for path in $paths /lib /usr/lib /usr/local/lib; do
3961                    path=`echo $path | sed -e 's;/*$;;'`
3962                    if [ $minusx "$path/cpp" ] && [ ! -d "$path/cpp" ]; then
3963                        cpp="$path/cpp"
3964                        break
3965                    fi
3966                done
3967                if [ ".$cpp" != . ]; then
3968                    (eval "$cpp $tmpfile.c >/dev/null") 2>$tmpfile.out
3969                    my_error=`grep -v '^ *+' $tmpfile.out`
3970                    if [ ".$my_error" != . ]; then
3971                        #   ok, we gave up...
3972                        cpp=''
3973                    fi
3974                fi
3975            fi
3976        fi
3977        rm -f $tmpfile >/dev/null 2>&1
3978        rm -f $tmpfile.c $tmpfile.out >/dev/null 2>&1
3979        if [ ".$cpp" != . ]; then
3980            echo "$cpp"
3981            shtool_exit 0
3982        fi
3983        shtool_exit 1
3984    fi
3985
3986    #   STANDARD SITUATION
3987    #   iterate over names
3988    for name in $namelist; do
3989        #   iterate over paths
3990        for path in $paths; do
3991            path=`echo $path | sed -e 's;/*$;;'`
3992            if [ $minusx "$path/$name" ] && [ ! -d "$path/$name" ]; then
3993                if [ ".$opt_s" != .yes ]; then
3994                    echo "$path/$name"
3995                fi
3996                shtool_exit 0
3997            fi
3998        done
3999    done
4000
4001    shtool_exit 1
4002    ;;
4003
4004esac
4005
4006shtool_exit 0
4007
4008