]> git.sur5r.net Git - openldap/blob - build/shtool
Ready for release
[openldap] / build / shtool
1 #!/bin/sh
2 # $OpenLDAP$
3 # This file is distributed with OpenLDAP Software, but is an
4 # an independently licensed program.
5
6 ##
7 ##  GNU shtool -- The GNU Portable Shell Tool
8 ##  Copyright (c) 1994-2002 Ralf S. Engelschall <rse@engelschall.com>
9 ##
10 ##  See http://www.gnu.org/software/shtool/ for more information.
11 ##  See ftp://ftp.gnu.org/gnu/shtool/ for latest version.
12 ##
13 ##  Version:  1.6.2 (02-Nov-2002)
14 ##  Contents: 6/19 available modules
15 ##
16
17 ##
18 ##  This program is free software; you can redistribute it and/or modify
19 ##  it under the terms of the GNU General Public License as published by
20 ##  the Free Software Foundation; either version 2 of the License, or
21 ##  (at your option) any later version.
22 ##
23 ##  This program is distributed in the hope that it will be useful,
24 ##  but WITHOUT ANY WARRANTY; without even the implied warranty of
25 ##  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26 ##  General Public License for more details.
27 ##
28 ##  You should have received a copy of the GNU General Public License
29 ##  along with this program; if not, write to the Free Software
30 ##  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
31 ##  USA, or contact Ralf S. Engelschall <rse@engelschall.com>.
32 ##
33 ##  NOTICE: Given that you include this file verbatim into your own
34 ##  source tree, you are justified in saying that it remains separate
35 ##  from your package, and that this way you are simply just using GNU
36 ##  shtool. So, in this situation, there is no requirement that your
37 ##  package itself is licensed under the GNU General Public License in
38 ##  order to take advantage of GNU shtool.
39 ##
40
41 ##
42 ##  Usage: shtool [<options>] [<cmd-name> [<cmd-options>] [<cmd-args>]]
43 ##
44 ##  Available commands:
45 ##    echo       Print string with optional construct expansion
46 ##    move       Move files with simultaneous substitution
47 ##    install    Install a program, script or datafile
48 ##    mkdir      Make one or more directories
49 ##    mkln       Make link with calculation of relative paths
50 ##    subst      Apply sed(1) substitution operations
51 ##
52 ##  Not available commands (because module was not built-in):
53 ##    mdate      Pretty-print modification time of a file or dir
54 ##    table      Pretty-print a field-separated list as a table
55 ##    prop       Display progress with a running propeller
56 ##    mkshadow   Make a shadow tree through symbolic links
57 ##    fixperm    Fix file permissions inside a source tree
58 ##    rotate     Logfile rotation
59 ##    tarball    Roll distribution tarballs
60 ##    guessos    Simple operating system guesser
61 ##    arx        Extended archive command
62 ##    slo        Separate linker options by library class
63 ##    scpp       Sharing C Pre-Processor
64 ##    version    Maintain a version information file
65 ##    path       Deal with program paths
66 ##
67
68 if [ $# -eq 0 ]; then
69     echo "$0:Error: invalid command line" 1>&2
70     echo "$0:Hint:  run \`$0 -h' for usage" 1>&2
71     exit 1
72 fi
73 if [ ".$1" = ".-h" -o ".$1" = ".--help" ]; then
74     echo "This is GNU shtool, version 1.6.2 (02-Nov-2002)"
75     echo "Copyright (c) 1994-2002 Ralf S. Engelschall <rse@engelschall.com>"
76     echo "Report bugs to <bug-shtool@gnu.org>"
77     echo ''
78     echo "Usage: shtool [<options>] [<cmd-name> [<cmd-options>] [<cmd-args>]]"
79     echo ''
80     echo 'Available global <options>:'
81     echo '  -v, --version   display shtool version information'
82     echo '  -h, --help      display shtool usage help page (this one)'
83     echo '  -d, --debug     display shell trace information'
84     echo '  -r, --recreate  recreate this shtool script via shtoolize'
85     echo ''
86     echo 'Available <cmd-name> [<cmd-options>] [<cmd-args>]:'
87     echo '  echo     [-n|--newline] [-e|--expand] [<str> ...]'
88     echo '  move     [-v|--verbose] [-t|--trace] [-e|--expand] [-p|--preserve]'
89     echo '           <src-file> <dst-file>'
90     echo '  install  [-v|--verbose] [-t|--trace] [-d|--mkdir] [-c|--copy]'
91     echo '           [-C|--compare-copy] [-s|--strip] [-m|--mode <mode>]'
92     echo '           [-o|--owner <owner>] [-g|--group <group>] [-e|--exec'
93     echo '           <sed-cmd>] <file> [<file> ...] <path>'
94     echo '  mkdir    [-t|--trace] [-f|--force] [-p|--parents] [-m|--mode'
95     echo '           <mode>] [-o|--owner <owner>] [-g|--group <group>] <dir>'
96     echo '           [<dir> ...]'
97     echo '  mkln     [-t|--trace] [-f|--force] [-s|--symbolic] <src-path>'
98     echo '           [<src-path> ...] <dst-path>'
99     echo '  subst    [-v|--verbose] [-t|--trace] [-n|--nop] [-s|--stealth]'
100     echo '           [-i|--interactive] [-b|--backup <ext>] [-e|--exec <cmd>]'
101     echo '           [-f|--file <cmd-file>] [<file>] [...]'
102     echo ''
103     echo 'Not available <cmd-name> (because module was not built-in):'
104     echo '  mdate    [-n|--newline] [-z|--zero] [-s|--shorten] [-d|--digits]'
105     echo '           [-f|--field-sep <str>] [-o|--order <spec>] <path>'
106     echo '  table    [-F|--field-sep <sep>] [-w|--width <width>] [-c|--columns'
107     echo '           <cols>] [-s|--strip <strip>] <str><sep><str>...'
108     echo '  prop     [-p|--prefix <str>]'
109     echo '  mkshadow [-v|--verbose] [-t|--trace] [-a|--all] <src-dir> <dst-dir>'
110     echo '  fixperm  [-v|--verbose] [-t|--trace] <path> [<path> ...]'
111     echo '  rotate   [-v|--verbose] [-t|--trace] [-f|--force] [-n|--num-files'
112     echo '           <count>] [-s|--size <size>] [-c|--copy] [-r|--remove]'
113     echo '           [-a|--archive-dir <dir>] [-z|--compress [<tool>:]<level>]'
114     echo '           [-b|--background] [-d|--delay] [-p|--pad <len>] [-o|--owner'
115     echo '           <owner>] [-g|--group <group>] [-m|--mode <mode>] [-M|--migrate'
116     echo '           <cmd>] [-P|--prolog <cmd>] [-E|--epilog <cmd>] <file> [...]'
117     echo '  tarball  [-t|--trace] [-v|--verbose] [-o|--output <tarball>]'
118     echo '           [-c|--compress <prog>] [-d|--directory <dir>] [-u|--user'
119     echo '           <user>] [-g|--group <group>] [-e|--exclude <pattern>]'
120     echo '           <path> [<path> ...]'
121     echo '  guessos  '
122     echo '  arx      [-t|--trace] [-C|--command <cmd>] <op> <archive> [<file>'
123     echo '           ...]'
124     echo '  slo      [-p|--prefix <str>] -- -L<dir> -l<lib> [-L<dir> -l<lib>'
125     echo '           ...]'
126     echo '  scpp     [-v|--verbose] [-p|--preserve] [-f|--filter <filter>]'
127     echo '           [-o|--output <ofile>] [-t|--template <tfile>] [-M|--mark'
128     echo '           <mark>] [-D|--define <dname>] [-C|--class <cname>]'
129     echo '           <file> [<file> ...]'
130     echo '  version  [-l|--language <lang>] [-n|--name <name>] [-p|--prefix'
131     echo '           <prefix>] [-s|--set <version>] [-e|--edit] [-i|--increase'
132     echo '           <knob>] [-d|--display <type>] <file>'
133     echo '  path     [-s|--suppress] [-r|--reverse] [-d|--dirname] [-b|--basename]'
134     echo '           [-m|--magic] [-p|--path <path>] <str> [<str> ...]'
135     echo ''
136     exit 0
137 fi
138 if [ ".$1" = ".-v" -o ".$1" = ."--version" ]; then
139     echo "GNU shtool 1.6.2 (02-Nov-2002)"
140     exit 0
141 fi
142 if [ ".$1" = ".-r" -o ".$1" = ."--recreate" ]; then
143     shtoolize -obuild/shtool echo move install mkdir mkln subst
144     exit 0
145 fi
146 if [ ".$1" = ".-d" -o ".$1" = ."--debug" ]; then
147     shift
148     set -x
149 fi
150 name=`echo "$0" | sed -e 's;.*/\([^/]*\)$;\1;' -e 's;-sh$;;' -e 's;\.sh$;;'`
151 case "$name" in
152     echo|move|install|mkdir|mkln|subst )
153         #   implicit tool command selection
154         tool="$name"
155         ;;
156     * )
157         #   explicit tool command selection
158         tool="$1"
159         shift
160         ;;
161 esac
162 arg_spec=""
163 opt_spec=""
164 gen_tmpfile=no
165
166 ##
167 ##  DISPATCH INTO SCRIPT PROLOG
168 ##
169
170 case $tool in
171     echo )
172         str_tool="echo"
173         str_usage="[-n|--newline] [-e|--expand] [<str> ...]"
174         arg_spec="0+"
175         opt_spec="n.e."
176         opt_alias="n:newline,e:expand"
177         opt_n=no
178         opt_e=no
179         ;;
180     move )
181         str_tool="move"
182         str_usage="[-v|--verbose] [-t|--trace] [-e|--expand] [-p|--preserve] <src-file> <dst-file>"
183         arg_spec="2="
184         opt_spec="v.t.e.p."
185         opt_alias="v:verbose,t:trace,e:expand,p:preserve"
186         opt_v=no
187         opt_t=no
188         opt_e=no
189         opt_p=no
190         ;;
191     install )
192         str_tool="install"
193         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>"
194         arg_spec="1+"
195         opt_spec="v.t.d.c.C.s.m:o:g:e+"
196         opt_alias="v:verbose,t:trace,d:mkdir,c:copy,C:compare-copy,s:strip,m:mode,o:owner,g:group,e:exec"
197         opt_v=no
198         opt_t=no
199         opt_d=no
200         opt_c=no
201         opt_C=no
202         opt_s=no
203         opt_m="0755"
204         opt_o=""
205         opt_g=""
206         opt_e=""
207         ;;
208     mkdir )
209         str_tool="mkdir"
210         str_usage="[-t|--trace] [-f|--force] [-p|--parents] [-m|--mode <mode>] [-o|--owner <owner>] [-g|--group <group>] <dir> [<dir> ...]"
211         arg_spec="1+"
212         opt_spec="t.f.p.m:o:g:"
213         opt_alias="t:trace,f:force,p:parents,m:mode,o:owner,g:group"
214         opt_t=no
215         opt_f=no
216         opt_p=no
217         opt_m=""
218         opt_o=""
219         opt_g=""
220         ;;
221     mkln )
222         str_tool="mkln"
223         str_usage="[-t|--trace] [-f|--force] [-s|--symbolic] <src-path> [<src-path> ...] <dst-path>"
224         arg_spec="2+"
225         opt_spec="t.f.s."
226         opt_alias="t:trace,f:force,s:symbolic"
227         opt_t=no
228         opt_f=no
229         opt_s=no
230         ;;
231     subst )
232         str_tool="subst"
233         str_usage="[-v|--verbose] [-t|--trace] [-n|--nop] [-s|--stealth] [-i|--interactive] [-b|--backup <ext>] [-e|--exec <cmd>] [-f|--file <cmd-file>] [<file>] [...]"
234         gen_tmpfile=yes
235         arg_spec="0+"
236         opt_spec="v.t.n.s.i.b:e+f:"
237         opt_alias="v:verbose,t:trace,n:nop,s:stealth,i:interactive,b:backup,e:exec,f:file"
238         opt_v=no
239         opt_t=no
240         opt_n=no
241         opt_s=no
242         opt_i=no
243         opt_b=""
244         opt_e=""
245         opt_f=""
246         ;;
247     -* )
248         echo "$0:Error: unknown option \`$tool'" 2>&1
249         echo "$0:Hint:  run \`$0 -h' for usage" 2>&1
250         exit 1
251         ;;
252     * )
253         echo "$0:Error: unknown command \`$tool'" 2>&1
254         echo "$0:Hint:  run \`$0 -h' for usage" 2>&1
255         exit 1
256         ;;
257 esac
258
259 ##
260 ##  COMMON UTILITY CODE
261 ##
262
263 #   commonly used ASCII values
264 ASC_TAB="       "
265 ASC_NL="
266 "
267
268 #   determine name of tool
269 if [ ".$tool" != . ]; then
270     #   used inside shtool script
271     toolcmd="$0 $tool"
272     toolcmdhelp="shtool $tool"
273     msgprefix="shtool:$tool"
274 else
275     #   used as standalone script
276     toolcmd="$0"
277     toolcmdhelp="sh $0"
278     msgprefix="$str_tool"
279 fi
280
281 #   parse argument specification string
282 eval `echo $arg_spec |\
283       sed -e 's/^\([0-9]*\)\([+=]\)/arg_NUMS=\1; arg_MODE=\2/'`
284
285 #   parse option specification string
286 eval `echo h.$opt_spec |\
287       sed -e 's/\([a-zA-Z0-9]\)\([.:+]\)/opt_MODE_\1=\2;/g'`
288
289 #   parse option alias string
290 eval `echo h:help,$opt_alias |\
291       tr 'x-' 'x_' | sed -e 's/\([a-zA-Z0-9]\):\([^,]*\),*/opt_ALIAS_\2=\1;/g'`
292
293 #   interate over argument line
294 opt_PREV=''
295 while [ $# -gt 0 ]; do
296     #   special option stops processing
297     if [ ".$1" = ".--" ]; then
298         shift
299         break
300     fi
301
302     #   determine option and argument
303     opt_ARG_OK=no
304     if [ ".$opt_PREV" != . ]; then
305         #   merge previous seen option with argument
306         opt_OPT="$opt_PREV"
307         opt_ARG="$1"
308         opt_ARG_OK=yes
309         opt_PREV=''
310     else
311         #   split argument into option and argument
312         case "$1" in
313             --[a-zA-Z0-9]*=*)
314                 eval `echo "x$1" |\
315                       sed -e 's/^x--\([a-zA-Z0-9-]*\)=\(.*\)$/opt_OPT="\1";opt_ARG="\2"/'`
316                 opt_STR=`echo $opt_OPT | tr 'x-' 'x_'`
317                 eval "opt_OPT=\${opt_ALIAS_${opt_STR}-${opt_OPT}}"
318                 ;;
319             --[a-zA-Z0-9]*)
320                 opt_OPT=`echo "x$1" | cut -c4-`
321                 opt_STR=`echo $opt_OPT | tr 'x-' 'x_'`
322                 eval "opt_OPT=\${opt_ALIAS_${opt_STR}-${opt_OPT}}"
323                 opt_ARG=''
324                 ;;
325             -[a-zA-Z0-9]*)
326                 eval `echo "x$1" |\
327                       sed -e 's/^x-\([a-zA-Z0-9]\)/opt_OPT="\1";/' \
328                           -e 's/";\(.*\)$/"; opt_ARG="\1"/'`
329                 ;;
330             -[a-zA-Z0-9])
331                 opt_OPT=`echo "x$1" | cut -c3-`
332                 opt_ARG=''
333                 ;;
334             *)
335                 break
336                 ;;
337         esac
338     fi
339
340     #   eat up option
341     shift
342
343     #   determine whether option needs an argument
344     eval "opt_MODE=\$opt_MODE_${opt_OPT}"
345     if [ ".$opt_ARG" = . -a ".$opt_ARG_OK" != .yes ]; then
346         if [ ".$opt_MODE" = ".:" -o ".$opt_MODE" = ".+" ]; then
347             opt_PREV="$opt_OPT"
348             continue
349         fi
350     fi
351
352     #   process option
353     case $opt_MODE in
354         '.' )
355             #   boolean option
356             eval "opt_${opt_OPT}=yes"
357             ;;
358         ':' )
359             #   option with argument (multiple occurances override)
360             eval "opt_${opt_OPT}=\"\$opt_ARG\""
361             ;;
362         '+' )
363             #   option with argument (multiple occurances append)
364             eval "opt_${opt_OPT}=\"\$opt_${opt_OPT}\${ASC_NL}\$opt_ARG\""
365             ;;
366         * )
367             echo "$msgprefix:Error: unknown option: \`$opt_OPT'" 1>&2
368             echo "$msgprefix:Hint:  run \`$toolcmdhelp -h' or \`man shtool' for details" 1>&2
369             exit 1
370             ;;
371     esac
372 done
373 if [ ".$opt_PREV" != . ]; then
374     echo "$msgprefix:Error: missing argument to option \`$opt_PREV'" 1>&2
375     echo "$msgprefix:Hint:  run \`$toolcmdhelp -h' or \`man shtool' for details" 1>&2
376     exit 1
377 fi
378
379 #   process help option
380 if [ ".$opt_h" = .yes ]; then
381     echo "Usage: $toolcmdhelp $str_usage"
382     exit 0
383 fi
384
385 #   complain about incorrect number of arguments
386 case $arg_MODE in
387     '=' )
388         if [ $# -ne $arg_NUMS ]; then
389             echo "$msgprefix:Error: invalid number of arguments (exactly $arg_NUMS expected)" 1>&2
390             echo "$msgprefix:Hint:  run \`$toolcmd -h' or \`man shtool' for details" 1>&2
391             exit 1
392         fi
393         ;;
394     '+' )
395         if [ $# -lt $arg_NUMS ]; then
396             echo "$msgprefix:Error: invalid number of arguments (at least $arg_NUMS expected)" 1>&2
397             echo "$msgprefix:Hint:  run \`$toolcmd -h' or \`man shtool' for details" 1>&2
398             exit 1
399         fi
400         ;;
401 esac
402
403 #   establish a temporary file on request
404 if [ ".$gen_tmpfile" = .yes ]; then
405     if [ ".$TMPDIR" != . ]; then
406         tmpdir="$TMPDIR"
407     elif [ ".$TEMPDIR" != . ]; then
408         tmpdir="$TEMPDIR"
409     else
410         tmpdir="/tmp"
411     fi
412     tmpfile="$tmpdir/.shtool.$$"
413     rm -f $tmpfile >/dev/null 2>&1
414     touch $tmpfile
415     chmod 600 $tmpfile
416 fi
417
418 ##
419 ##  DISPATCH INTO SCRIPT BODY
420 ##
421
422 case $tool in
423
424 echo )
425     ##
426     ##  echo -- Print string with optional construct expansion
427     ##  Copyright (c) 1998-2002 Ralf S. Engelschall <rse@engelschall.com>
428     ##  Originally written for WML as buildinfo
429     ##
430     
431     text="$*"
432     
433     #   check for broken escape sequence expansion
434     seo=''
435     bytes=`echo '\1' | wc -c | awk '{ printf("%s", $1); }'`
436     if [ ".$bytes" != .3 ]; then
437         bytes=`echo -E '\1' | wc -c | awk '{ printf("%s", $1); }'`
438         if [ ".$bytes" = .3 ]; then
439             seo='-E'
440         fi
441     fi
442     
443     #   check for existing -n option (to suppress newline)
444     minusn=''
445     bytes=`echo -n 123 2>/dev/null | wc -c | awk '{ printf("%s", $1); }'`
446     if [ ".$bytes" = .3 ]; then
447         minusn='-n'
448     fi
449     
450     #   determine terminal bold sequence
451     term_bold=''
452     term_norm=''
453     if [ ".$opt_e" = .yes -a ".`echo $text | egrep '%[Bb]'`" != . ]; then
454         case $TERM in
455             #   for the most important terminal types we directly know the sequences
456             xterm|xterm*|vt220|vt220*)
457                 term_bold=`awk 'BEGIN { printf("%c%c%c%c", 27, 91, 49, 109); }' </dev/null 2>/dev/null`
458                 term_norm=`awk 'BEGIN { printf("%c%c%c", 27, 91, 109); }' </dev/null 2>/dev/null`
459                 ;;
460             vt100|vt100*|cygwin)
461                 term_bold=`awk 'BEGIN { printf("%c%c%c%c%c%c", 27, 91, 49, 109, 0, 0); }' </dev/null 2>/dev/null`
462                 term_norm=`awk 'BEGIN { printf("%c%c%c%c%c", 27, 91, 109, 0, 0); }' </dev/null 2>/dev/null`
463                 ;;
464             #   for all others, we try to use a possibly existing `tput' or `tcout' utility
465             * )
466                 paths=`echo $PATH | sed -e 's/:/ /g'`
467                 for tool in tput tcout; do
468                     for dir in $paths; do
469                         if [ -r "$dir/$tool" ]; then
470                             for seq in bold md smso; do # 'smso' is last
471                                 bold="`$dir/$tool $seq 2>/dev/null`"
472                                 if [ ".$bold" != . ]; then
473                                     term_bold="$bold"
474                                     break
475                                 fi
476                             done
477                             if [ ".$term_bold" != . ]; then
478                                 for seq in sgr0 me rmso init reset; do # 'reset' is last
479                                     norm="`$dir/$tool $seq 2>/dev/null`"
480                                     if [ ".$norm" != . ]; then
481                                         term_norm="$norm"
482                                         break
483                                     fi
484                                 done
485                             fi
486                             break
487                         fi
488                     done
489                     if [ ".$term_bold" != . -a ".$term_norm" != . ]; then
490                         break;
491                     fi
492                 done
493                 ;;
494         esac
495         if [ ".$term_bold" = . -o ".$term_norm" = . ]; then
496             echo "$msgprefix:Warning: unable to determine terminal sequence for bold mode" 1>&2
497             term_bold=''
498             term_norm=''
499         fi
500     fi
501     
502     #   determine user name
503     username=''
504     if [ ".$opt_e" = .yes -a ".`echo $text | egrep '%[uUgG]'`" != . ]; then
505         username="$LOGNAME"
506         if [ ".$username" = . ]; then
507             username="$USER"
508             if [ ".$username" = . ]; then
509                 username="`(whoami) 2>/dev/null |\
510                            awk '{ printf("%s", $1); }'`"
511                 if [ ".$username" = . ]; then
512                     username="`(who am i) 2>/dev/null |\
513                                awk '{ printf("%s", $1); }'`"
514                     if [ ".$username" = . ]; then
515                         username='unknown'
516                     fi
517                 fi
518             fi
519         fi
520     fi
521     
522     #   determine user id
523     userid=''
524     if [ ".$opt_e" = .yes -a ".`echo $text | egrep '%U'`" != . ]; then
525         userid="`(id -u) 2>/dev/null`"
526         if [ ".$userid" = . ]; then
527             str="`(id) 2>/dev/null`"
528             if [ ".`echo $str | grep '^uid[     ]*=[    ]*[0-9]*('`" != . ]; then
529                 userid=`echo $str | sed -e 's/^uid[     ]*=[    ]*//' -e 's/(.*//'`
530             fi
531             if [ ".$userid" = . ]; then
532                 userid=`egrep "^${username}:" /etc/passwd 2>/dev/null | \
533                         sed -e 's/[^:]*:[^:]*://' -e 's/:.*$//'`
534                 if [ ".$userid" = . ]; then
535                     userid=`(ypcat passwd) 2>/dev/null |
536                             egrep "^${username}:" | \
537                             sed -e 's/[^:]*:[^:]*://' -e 's/:.*$//'`
538                     if [ ".$userid" = . ]; then
539                         userid='?'
540                     fi
541                 fi
542             fi
543         fi
544     fi
545     
546     #   determine (primary) group id
547     groupid=''
548     if [ ".$opt_e" = .yes -a ".`echo $text | egrep '%[gG]'`" != . ]; then
549         groupid=`egrep "^${username}:" /etc/passwd 2>/dev/null | \
550                  sed -e 's/[^:]*:[^:]*:[^:]*://' -e 's/:.*$//'`
551         if [ ".$groupid" = . ]; then
552             groupid=`(ypcat passwd) 2>/dev/null | egrep "^${username}:" | \
553                      sed -e 's/[^:]*:[^:]*:[^:]*://' -e 's/:.*$//'`
554             if [ ".$groupid" = . ]; then
555                 groupid='?'
556             fi
557         fi
558     fi
559     
560     #   determine (primary) group name
561     groupname=''
562     if [ ".$opt_e" = .yes -a ".`echo $text | egrep '%g'`" != . ]; then
563         groupname=`egrep "^[^:]*:[^:]*:${groupid}:" /etc/group 2>/dev/null | \
564                    sed -e 's/:.*$//'`
565         if [ ".$groupname" = . ]; then
566             groupname=`(ypcat group) 2>/dev/null | \
567                        egrep "^[^:]*:[^:]*:${groupid}:" | \
568                        sed -e 's/:.*$//'`
569             if [ ".$groupname" = . ]; then
570                 groupname='?'
571             fi
572         fi
573     fi
574     
575     #   determine host and domain name
576     hostname=''
577     domainname=''
578     if [ ".$opt_e" = .yes -a ".`echo $text | egrep '%h'`" != . ]; then
579         hostname="`(uname -n) 2>/dev/null |\
580                    awk '{ printf("%s", $1); }'`"
581         if [ ".$hostname" = . ]; then
582             hostname="`(hostname) 2>/dev/null |\
583                        awk '{ printf("%s", $1); }'`"
584             if [ ".$hostname" = . ]; then
585                 hostname='unknown'
586             fi
587         fi
588         case $hostname in
589             *.* )
590                 domainname=".`echo $hostname | cut -d. -f2-`"
591                 hostname="`echo $hostname | cut -d. -f1`"
592                 ;;
593         esac
594     fi
595     if [ ".$opt_e" = .yes -a ".`echo $text | egrep '%d'`" != . ]; then
596         if [ ".$domainname" = . ]; then
597             if [ -f /etc/resolv.conf ]; then
598                 domainname="`egrep '^[  ]*domain' /etc/resolv.conf | sed -e 'q' |\
599                              sed -e 's/.*domain//' \
600                                  -e 's/^[       ]*//' -e 's/^ *//' -e 's/^      *//' \
601                                  -e 's/^\.//' -e 's/^/./' |\
602                              awk '{ printf("%s", $1); }'`"
603                 if [ ".$domainname" = . ]; then
604                     domainname="`egrep '^[      ]*search' /etc/resolv.conf | sed -e 'q' |\
605                                  sed -e 's/.*search//' \
606                                      -e 's/^[   ]*//' -e 's/^ *//' -e 's/^      *//' \
607                                      -e 's/ .*//' -e 's/        .*//' \
608                                      -e 's/^\.//' -e 's/^/./' |\
609                                  awk '{ printf("%s", $1); }'`"
610                 fi
611             fi
612         fi
613     fi
614     
615     #   determine current time
616     time_day=''
617     time_month=''
618     time_year=''
619     time_monthname=''
620     if [ ".$opt_e" = .yes -a ".`echo $text | egrep '%[DMYm]'`" != . ]; then
621         time_day=`date '+%d'`
622         time_month=`date '+%m'`
623         time_year=`date '+%Y' 2>/dev/null`
624         if [ ".$time_year" = . ]; then
625             time_year=`date '+%y'`
626             case $time_year in
627                 [5-9][0-9]) time_year="19$time_year" ;;
628                 [0-4][0-9]) time_year="20$time_year" ;;
629             esac
630         fi
631         case $time_month in
632             1|01) time_monthname='Jan' ;;
633             2|02) time_monthname='Feb' ;;
634             3|03) time_monthname='Mar' ;;
635             4|04) time_monthname='Apr' ;;
636             5|05) time_monthname='May' ;;
637             6|06) time_monthname='Jun' ;;
638             7|07) time_monthname='Jul' ;;
639             8|08) time_monthname='Aug' ;;
640             9|09) time_monthname='Sep' ;;
641               10) time_monthname='Oct' ;;
642               11) time_monthname='Nov' ;;
643               12) time_monthname='Dec' ;;
644         esac
645     fi
646     
647     #   expand special ``%x'' constructs
648     if [ ".$opt_e" = .yes ]; then
649         text=`echo $seo "$text" |\
650               sed -e "s/%B/${term_bold}/g" \
651                   -e "s/%b/${term_norm}/g" \
652                   -e "s/%u/${username}/g" \
653                   -e "s/%U/${userid}/g" \
654                   -e "s/%g/${groupname}/g" \
655                   -e "s/%G/${groupid}/g" \
656                   -e "s/%h/${hostname}/g" \
657                   -e "s/%d/${domainname}/g" \
658                   -e "s/%D/${time_day}/g" \
659                   -e "s/%M/${time_month}/g" \
660                   -e "s/%Y/${time_year}/g" \
661                   -e "s/%m/${time_monthname}/g" 2>/dev/null`
662     fi
663     
664     #   create output
665     if [ .$opt_n = .no ]; then
666         echo $seo "$text"
667     else
668         #   the harder part: echo -n is best, because
669         #   awk may complain about some \xx sequences.
670         if [ ".$minusn" != . ]; then
671             echo $seo $minusn "$text"
672         else
673             echo dummy | awk '{ printf("%s", TEXT); }' TEXT="$text"
674         fi
675     fi
676     ;;
677
678 move )
679     ##
680     ##  move -- Move files with simultaneous substitution
681     ##  Copyright (c) 1999-2002 Ralf S. Engelschall <rse@engelschall.com>
682     ##  Originally written for shtool
683     ##
684     
685     src="$1"
686     dst="$2"
687     
688     #   consistency checks
689     if [ ".$src" = . -o ".$dst" = . ]; then
690         echo "$msgprefix:Error: Invalid arguments" 1>&2
691         exit 1
692     fi
693     if [ ".$src" = ".$dst" ]; then
694         echo "$msgprefix:Error: Source and destination files are the same" 1>&2
695         exit 1
696     fi
697     expsrc="$src"
698     if [ ".$opt_e" = .yes ]; then
699         expsrc="`echo $expsrc`"
700     fi
701     if [ ".$opt_e" = .yes ]; then
702         if [ ".`echo "$src" | sed -e 's;^.*\\*.*$;;'`" = ".$src" ]; then
703             echo "$msgprefix:Error: Source doesn't contain wildcard ('*'): $dst" 1>&2
704             exit 1
705         fi
706         if [ ".`echo "$dst" | sed -e 's;^.*%[1-9].*$;;'`" = ".$dst" ]; then
707             echo "$msgprefix:Error: Destination doesn't contain substitution ('%N'): $dst" 1>&2
708             exit 1
709         fi
710         if [ ".$expsrc" = ".$src" ]; then
711             echo "$msgprefix:Error: Sources not found or no asterisk : $src" 1>&2
712             exit 1
713         fi
714     else
715         if [ ! -r "$src" ]; then
716             echo "$msgprefix:Error: Source not found: $src" 1>&2
717             exit 1
718         fi
719     fi
720     
721     #   determine substitution patterns
722     if [ ".$opt_e" = .yes ]; then
723         srcpat=`echo "$src" | sed -e 's/\\./\\\\./g' -e 's/;/\\;/g' -e 's;\\*;\\\\(.*\\\\);g'`
724         dstpat=`echo "$dst" | sed -e 's;%\([1-9]\);\\\\\1;g'`
725     fi
726     
727     #   iterate over source(s)
728     for onesrc in $expsrc; do
729         if [ .$opt_e = .yes ]; then
730             onedst=`echo $onesrc | sed -e "s;$srcpat;$dstpat;"`
731         else
732             onedst="$dst"
733         fi
734         errorstatus=0
735         if [ ".$opt_v" = .yes ]; then
736             echo "$onesrc -> $onedst"
737         fi
738         if [ ".$opt_p" = .yes ]; then
739             if [ -r $onedst ]; then
740                 if cmp -s $onesrc $onedst; then
741                     if [ ".$opt_t" = .yes ]; then
742                         echo "rm -f $onesrc" 1>&2
743                     fi
744                     rm -f $onesrc || errorstatus=$?
745                 else
746                     if [ ".$opt_t" = .yes ]; then
747                         echo "mv -f $onesrc $onedst" 1>&2
748                     fi
749                     mv -f $onesrc $onedst || errorstatus=$?
750                 fi
751             else
752                 if [ ".$opt_t" = .yes ]; then
753                     echo "mv -f $onesrc $onedst" 1>&2
754                 fi
755                 mv -f $onesrc $onedst || errorstatus=$?
756             fi
757         else
758             if [ ".$opt_t" = .yes ]; then
759                 echo "mv -f $onesrc $onedst" 1>&2
760             fi
761             mv -f $onesrc $onedst || errorstatus=$?
762         fi
763         if [ $errorstatus -ne 0 ]; then
764             break;
765         fi
766     done
767     exit $errorstatus
768     ;;
769
770 install )
771     ##
772     ##  install -- Install a program, script or datafile
773     ##  Copyright (c) 1997-2002 Ralf S. Engelschall <rse@engelschall.com>
774     ##  Originally written for shtool
775     ##
776     
777     #   special case: "shtool install -d <dir> [...]" internally
778     #   maps to "shtool mkdir -f -p -m 755 <dir> [...]"
779     if [ "$opt_d" = yes ]; then
780         cmd="$0 mkdir -f -p -m 755"
781         if [ ".$opt_o" != . ]; then
782             cmd="$cmd -o '$opt_o'"
783         fi
784         if [ ".$opt_g" != . ]; then
785             cmd="$cmd -g '$opt_g'"
786         fi
787         if [ ".$opt_v" = .yes ]; then
788             cmd="$cmd -v"
789         fi
790         if [ ".$opt_t" = .yes ]; then
791             cmd="$cmd -t"
792         fi
793         for dir in "$@"; do
794             eval "$cmd $dir" || exit $?
795         done
796         exit 0
797     fi
798     
799     #   determine source(s) and destination
800     argc=$#
801     srcs=""
802     while [ $# -gt 1 ]; do
803         srcs="$srcs $1"
804         shift
805     done
806     dstpath="$1"
807     
808     #   type check for destination
809     dstisdir=0
810     if [ -d $dstpath ]; then
811         dstpath=`echo "$dstpath" | sed -e 's:/$::'`
812         dstisdir=1
813     fi
814     
815     #   consistency check for destination
816     if [ $argc -gt 2 -a $dstisdir = 0 ]; then
817         echo "$msgprefix:Error: multiple sources require destination to be directory" 1>&2
818         exit 1
819     fi
820     
821     #   iterate over all source(s)
822     for src in $srcs; do
823         dst=$dstpath
824     
825         #   if destination is a directory, append the input filename
826         if [ $dstisdir = 1 ]; then
827             dstfile=`echo "$src" | sed -e 's;.*/\([^/]*\)$;\1;'`
828             dst="$dst/$dstfile"
829         fi
830     
831         #   check for correct arguments
832         if [ ".$src" = ".$dst" ]; then
833             echo "$msgprefix:Warning: source and destination are the same - skipped" 1>&2
834             continue
835         fi
836         if [ -d "$src" ]; then
837             echo "$msgprefix:Warning: source \`$src' is a directory - skipped" 1>&2
838             continue
839         fi
840     
841         #   make a temp file name in the destination directory
842         dsttmp=`echo $dst |\
843                 sed -e 's;[^/]*$;;' -e 's;\(.\)/$;\1;' -e 's;^$;.;' \
844                     -e "s;\$;/#INST@$$#;"`
845     
846         #   verbosity
847         if [ ".$opt_v" = .yes ]; then
848             echo "$src -> $dst" 1>&2
849         fi
850     
851         #   copy or move the file name to the temp name
852         #   (because we might be not allowed to change the source)
853         if [ ".$opt_C" = .yes ]; then
854             opt_c=yes
855         fi
856         if [ ".$opt_c" = .yes ]; then
857             if [ ".$opt_t" = .yes ]; then
858                 echo "cp $src $dsttmp" 1>&2
859             fi
860             cp $src $dsttmp || exit $?
861         else
862             if [ ".$opt_t" = .yes ]; then
863                 echo "mv $src $dsttmp" 1>&2
864             fi
865             mv $src $dsttmp || exit $?
866         fi
867     
868         #   adjust the target file
869         if [ ".$opt_e" != . ]; then
870             sed='sed'
871             OIFS="$IFS"; IFS="$ASC_NL"; set -- $opt_e; IFS="$OIFS"
872             for e
873             do
874                 sed="$sed -e '$e'"
875             done
876             cp $dsttmp $dsttmp.old
877             eval "$sed <$dsttmp.old >$dsttmp" || exit $?
878             rm -f $dsttmp.old
879         fi
880         if [ ".$opt_s" = .yes ]; then
881             if [ ".$opt_t" = .yes ]; then
882                 echo "strip $dsttmp" 1>&2
883             fi
884             strip $dsttmp || exit $?
885         fi
886         if [ ".$opt_o" != . ]; then
887             if [ ".$opt_t" = .yes ]; then
888                 echo "chown $opt_o $dsttmp" 1>&2
889             fi
890             chown $opt_o $dsttmp || exit $?
891         fi
892         if [ ".$opt_g" != . ]; then
893             if [ ".$opt_t" = .yes ]; then
894                 echo "chgrp $opt_g $dsttmp" 1>&2
895             fi
896             chgrp $opt_g $dsttmp || exit $?
897         fi
898         if [ ".$opt_m" != ".-" ]; then
899             if [ ".$opt_t" = .yes ]; then
900                 echo "chmod $opt_m $dsttmp" 1>&2
901             fi
902             chmod $opt_m $dsttmp || exit $?
903         fi
904     
905         #   determine whether to do a quick install
906         #   (has to be done _after_ the strip was already done)
907         quick=no
908         if [ ".$opt_C" = .yes ]; then
909             if [ -r $dst ]; then
910                 if cmp -s $src $dst; then
911                     quick=yes
912                 fi
913             fi
914         fi
915     
916         #   finally, install the file to the real destination
917         if [ $quick = yes ]; then
918             if [ ".$opt_t" = .yes ]; then
919                 echo "rm -f $dsttmp" 1>&2
920             fi
921             rm -f $dsttmp
922         else
923             if [ ".$opt_t" = .yes ]; then
924                 echo "rm -f $dst && mv $dsttmp $dst" 1>&2
925             fi
926             rm -f $dst && mv $dsttmp $dst
927         fi
928     done
929     ;;
930
931 mkdir )
932     ##
933     ##  mkdir -- Make one or more directories
934     ##  Copyright (c) 1996-2002 Ralf S. Engelschall <rse@engelschall.com>
935     ##  Originally written for public domain by Noah Friedman <friedman@prep.ai.mit.edu>
936     ##  Cleaned up and enhanced for shtool
937     ##
938     
939     errstatus=0
940     for p in ${1+"$@"}; do
941         #   if the directory already exists...
942         if [ -d "$p" ]; then
943             if [ ".$opt_f" = .no -a ".$opt_p" = .no ]; then
944                 echo "$msgprefix:Error: directory already exists: $p" 1>&2
945                 errstatus=1
946                 break
947             else
948                 continue
949             fi
950         fi
951         #   if the directory has to be created...
952         if [ ".$opt_p" = .no ]; then
953             if [ ".$opt_t" = .yes ]; then
954                 echo "mkdir $p" 1>&2
955             fi
956             mkdir $p || errstatus=$?
957             if [ ".$opt_o" != . ]; then
958                 if [ ".$opt_t" = .yes ]; then
959                     echo "chown $opt_o $p" 1>&2
960                 fi
961                 chown $opt_o $p || errstatus=$?
962             fi
963             if [ ".$opt_g" != . ]; then
964                 if [ ".$opt_t" = .yes ]; then
965                     echo "chgrp $opt_g $p" 1>&2
966                 fi
967                 chgrp $opt_g $p || errstatus=$?
968             fi
969             if [ ".$opt_m" != . ]; then
970                 if [ ".$opt_t" = .yes ]; then
971                     echo "chmod $opt_m $p" 1>&2
972                 fi
973                 chmod $opt_m $p || errstatus=$?
974             fi
975         else
976             #   the smart situation
977             set fnord `echo ":$p" |\
978                        sed -e 's/^:\//%/' \
979                            -e 's/^://' \
980                            -e 's/\// /g' \
981                            -e 's/^%/\//'`
982             shift
983             pathcomp=''
984             for d in ${1+"$@"}; do
985                 pathcomp="$pathcomp$d"
986                 case "$pathcomp" in
987                     -* ) pathcomp="./$pathcomp" ;;
988                 esac
989                 if [ ! -d "$pathcomp" ]; then
990                     if [ ".$opt_t" = .yes ]; then
991                         echo "mkdir $pathcomp" 1>&2
992                     fi
993                     mkdir $pathcomp || errstatus=$?
994                     if [ ".$opt_o" != . ]; then
995                         if [ ".$opt_t" = .yes ]; then
996                             echo "chown $opt_o $pathcomp" 1>&2
997                         fi
998                         chown $opt_o $pathcomp || errstatus=$?
999                     fi
1000                     if [ ".$opt_g" != . ]; then
1001                         if [ ".$opt_t" = .yes ]; then
1002                             echo "chgrp $opt_g $pathcomp" 1>&2
1003                         fi
1004                         chgrp $opt_g $pathcomp || errstatus=$?
1005                     fi
1006                     if [ ".$opt_m" != . ]; then
1007                         if [ ".$opt_t" = .yes ]; then
1008                             echo "chmod $opt_m $pathcomp" 1>&2
1009                         fi
1010                         chmod $opt_m $pathcomp || errstatus=$?
1011                     fi
1012                 fi
1013                 pathcomp="$pathcomp/"
1014             done
1015         fi
1016     done
1017     exit $errstatus
1018     ;;
1019
1020 mkln )
1021     ##
1022     ##  mkln -- Make link with calculation of relative paths
1023     ##  Copyright (c) 1999-2002 Ralf S. Engelschall <rse@engelschall.com>
1024     ##  Originally written for shtool
1025     ##
1026     
1027     args=$?
1028     srcs=""
1029     while [ $# -gt 1 ]; do
1030         srcs="$srcs $1"
1031         shift
1032     done
1033     dst="$1"
1034     if [ ! -d $dst ]; then
1035         if [ $args -gt 2 ]; then
1036             echo "$msgprefix:Error: multiple sources not allowed when target isn't a directory" 1>&2
1037             exit 1
1038         fi
1039     fi
1040     
1041     #   determine link options
1042     lnopt=""
1043     if [ ".$opt_f" = .yes ]; then
1044         lnopt="$lnopt -f"
1045     fi
1046     if [ ".$opt_s" = .yes ]; then
1047         lnopt="$lnopt -s"
1048     fi
1049     
1050     #   iterate over sources
1051     for src in $srcs; do
1052         #   determine if one of the paths is an absolute path,
1053         #   because then we _have_ to use an absolute symlink
1054         oneisabs=0
1055         srcisabs=0
1056         dstisabs=0
1057         case $src in
1058             /* ) oneisabs=1; srcisabs=1 ;;
1059         esac
1060         case $dst in
1061             /* ) oneisabs=1; dstisabs=1 ;;
1062         esac
1063     
1064         #   split source and destination into dir and base name
1065         if [ -d $src ]; then
1066             srcdir=`echo $src | sed -e 's;/*$;;'`
1067             srcbase=""
1068         else
1069             srcdir=`echo  $src | sed -e 's;^[^/]*$;;' -e 's;^\(.*/\)[^/]*$;\1;' -e 's;\(.\)/$;\1;'`
1070             srcbase=`echo $src | sed -e 's;.*/\([^/]*\)$;\1;'`
1071         fi
1072         if [ -d $dst ]; then
1073             dstdir=`echo $dst | sed -e 's;/*$;;'`
1074             dstbase=""
1075         else
1076             dstdir=`echo  $dst | sed -e 's;^[^/]*$;;' -e 's;^\(.*/\)[^/]*$;\1;' -e 's;\(.\)/$;\1;'`
1077             dstbase=`echo $dst | sed -e 's;.*/\([^/]*\)$;\1;'`
1078         fi
1079     
1080         #   consistency check
1081         if [ ".$dstdir" != . ]; then
1082             if [ ! -d $dstdir ]; then
1083                 echo "$msgprefix:Error: destination directory not found: $dstdir" 1>&2
1084                 exit 1
1085             fi
1086         fi
1087     
1088         #   make sure the source is reachable from the destination
1089         if [ $dstisabs = 1 ]; then
1090             if [ $srcisabs = 0 ]; then
1091                 if [ -d $srcdir ]; then
1092                     srcdir="`cd $srcdir; pwd | sed -e 's;/*$;;'`"
1093                     srcisabs=1
1094                     oneisabs=1
1095                 fi
1096             fi
1097         fi
1098     
1099         #   split away a common prefix
1100         prefix=""
1101         if [ ".$srcdir" = ".$dstdir" -a ".$srcdir" != . ]; then
1102             prefix="$srcdir/"
1103             srcdir=""
1104             dstdir=""
1105         else
1106             while [ ".$srcdir" != . -a ".$dstdir" != . ]; do
1107                 presrc=`echo $srcdir | sed -e 's;^\([^/]*\)/.*;\1;'`
1108                 predst=`echo $dstdir | sed -e 's;^\([^/]*\)/.*;\1;'`
1109                 if [ ".$presrc" != ".$predst" ]; then
1110                     break
1111                 fi
1112                 prefix="$prefix$presrc/"
1113                 srcdir=`echo $srcdir | sed -e 's;^[^/]*/*;;'`
1114                 dstdir=`echo $dstdir | sed -e 's;^[^/]*/*;;'`
1115             done
1116         fi
1117     
1118         #   destination prefix is just the common prefix
1119         dstpre="$prefix"
1120     
1121         #   determine source prefix which is the reverse directory
1122         #   step-up corresponding to the destination directory
1123         srcpre=""
1124         if [ $oneisabs = 0 ] || [ ".$prefix" != . -a ".$prefix" != ./ ]; then
1125             pl="$dstdir/"
1126             OIFS="$IFS"; IFS='/'
1127             for pe in $pl; do
1128                 [ ".$pe" = . ] && continue
1129                 srcpre="../$srcpre"
1130             done
1131             IFS="$OIFS"
1132         else
1133             if [ $srcisabs = 1 ]; then
1134                 srcpre="$prefix"
1135             fi
1136         fi
1137     
1138         #   determine destination symlink name
1139         if [ ".$dstbase" = . ]; then
1140             if [ ".$srcbase" != . ]; then
1141                 dstbase="$srcbase"
1142             else
1143                 dstbase=`echo "$prefix$srcdir" | sed -e 's;/*$;;' -e 's;.*/\([^/]*\)$;\1;'`
1144             fi
1145         fi
1146     
1147         #   now finalize source and destination directory paths
1148         srcdir=`echo $srcdir | sed -e 's;\([^/]\)$;\1/;'`
1149         dstdir=`echo $dstdir | sed -e 's;\([^/]\)$;\1/;'`
1150     
1151         #   run the final link command
1152         if [ ".$opt_t" = .yes ]; then
1153             echo "ln$lnopt $srcpre$srcdir$srcbase $dstpre$dstdir$dstbase"
1154         fi
1155         eval ln$lnopt $srcpre$srcdir$srcbase $dstpre$dstdir$dstbase
1156     done
1157     ;;
1158
1159 subst )
1160     ##
1161     ##  subst -- Apply sed(1) substitution operations
1162     ##  Copyright (c) 2001-2002 Ralf S. Engelschall <rse@engelschall.com>
1163     ##  Originally written for OpenPKG's rpmtool
1164     ##
1165     
1166     #   remember optional list of file(s)
1167     files="$*"
1168     
1169     #   parameter consistency check
1170     if [ $# -eq 0 -a ".$opt_b" != . ]; then
1171         echo "$msgprefix:Error: option -b cannot be applied to stdin" 1>&2
1172         exit 1
1173     fi
1174     if [ $# -eq 0 -a ".$opt_s" = .yes ]; then
1175         echo "$msgprefix:Error: option -s cannot be applied to stdin" 1>&2
1176         exit 1
1177     fi
1178     
1179     #   build underlying sed(1) command
1180     sedcmd='sed'
1181     if [ ".$opt_e" != . ]; then
1182         OIFS="$IFS"; IFS="$ASC_NL"; set -- $opt_e; IFS="$OIFS"
1183         for e
1184         do
1185             sedcmd="$sedcmd -e '$e'" 
1186         done
1187     elif [ ".$opt_f" != . ]; then
1188         if [ ! -f $opt_f ]; then
1189             echo "$msgprefix:Error: command file \`$opt_f' not found or not a regular file" 1>&2
1190             exit 1
1191         fi
1192         sedcmd="$sedcmd -f '$opt_f'"
1193     else
1194         echo "$msgprefix:Error: either -e option(s) or -f option required" 1>&2
1195         exit 1
1196     fi
1197     
1198     #   determine extension for original file
1199     orig=".orig"
1200     if [ ".$opt_b" != . ]; then
1201         orig="$opt_b"
1202     fi
1203     
1204     #   apply sed(1) operation(s)
1205     if [ ".$files" != . ]; then
1206         #   apply operation(s) to files
1207         for file in $files; do
1208             test ".$file" = . && continue
1209             if [ ! -f $file ]; then
1210                 echo "$msgprefix:Warning: file \`$file' not found or not a regular file" 1>&2
1211                 continue
1212             fi
1213     
1214             #   handle interactive mode
1215             if [ ".$opt_i" = .yes ]; then
1216                 eval "$sedcmd <$file >$file.new"
1217                 skip=no
1218                 if cmp $file $file.new >/dev/null 2>&1; then
1219                     rm -f $file.new
1220                     skip=yes
1221                 else
1222                     (diff -U1 $file $file.new >$tmpfile) 2>/dev/null
1223                     if [ ".`cat $tmpfile`" = . ]; then
1224                         (diff -C1 $file $file.new >$tmpfile) 2>/dev/null
1225                         if [ ".`cat $tmpfile`" = . ]; then
1226                             echo "$msgprefix:Warning: unable to show difference for file \`$file'" 1>&2
1227                             cp /dev/null $tmpfile
1228                         fi
1229                     fi
1230                     rm -f $file.new
1231                     cat $tmpfile
1232                     echo dummy | awk '{ printf("%s", TEXT); }' TEXT=">>> Apply [Y/n]: "
1233                     read input
1234                     if [ ".$input" != .Y ] &&\
1235                        [ ".$input" != .y ] &&\
1236                        [ ".$input" != . ]; then
1237                        skip=yes
1238                     fi
1239                 fi
1240                 if [ ".$skip" = .yes ]; then
1241                     if [ ".$opt_v" = .yes ]; then
1242                         echo "file \`$file' -- skipped" 1>&2
1243                     fi
1244                     continue
1245                 fi
1246             fi
1247     
1248             #   apply sed(1) operation(s)
1249             if [ ".$opt_v" = .yes ]; then
1250                 echo "patching \`$file'" 1>&2
1251             fi
1252             if [ ".$opt_t" = .yes ]; then
1253                 echo "\$ cp -p $file $file$orig"
1254                 echo "\$ $sedcmd <$file$orig >$file"
1255             fi
1256             if [ ".$opt_n" = .no ]; then
1257                 cp -p $file $file$orig
1258                 eval "$sedcmd <$file$orig >$file"
1259             fi
1260     
1261             #   optionally fix timestamp
1262             if [ ".$opt_s" = .yes ]; then
1263                 if [ ".$opt_t" = .yes ]; then
1264                     echo "\$ touch -r $file$orig $file"
1265                 fi
1266                 if [ ".$opt_n" = .no ]; then
1267                     touch -r $file$orig $file
1268                 fi
1269             fi
1270     
1271             #   optionally remove preserved original file
1272             if [ ".$opt_b" = . ]; then
1273                 if [ ".$opt_t" = .yes ]; then
1274                     echo "\$ rm -f $file$orig"
1275                 fi
1276                 if [ ".$opt_n" = .no ]; then
1277                     rm -f $file$orig
1278                 fi
1279             fi
1280         done
1281     else
1282         #   apply operation(s) to stdin/stdout
1283         if [ ".$opt_v" = .yes ]; then
1284             echo "patching <stdin>" 1>&2
1285         fi
1286         if [ ".$opt_t" = .yes ]; then
1287             echo "\$ $sedcmd"
1288         fi
1289         if [ ".$opt_n" = .no ]; then
1290             eval "$sedcmd"
1291         fi
1292     fi
1293     ;;
1294
1295 esac
1296
1297 exit 0
1298
1299 ##EOF##