xref: /netbsd-src/external/gpl2/texinfo/dist/install-sh (revision 29619d2afe564e54d657b83e5a3ae89584f83720)
1*29619d2aSchristos#!/bin/sh
2*29619d2aSchristos# install - install a program, script, or datafile
3*29619d2aSchristos
4*29619d2aSchristosscriptversion=2004-12-17.09
5*29619d2aSchristos
6*29619d2aSchristos# This originates from X11R5 (mit/util/scripts/install.sh), which was
7*29619d2aSchristos# later released in X11R6 (xc/config/util/install.sh) with the
8*29619d2aSchristos# following copyright and license.
9*29619d2aSchristos#
10*29619d2aSchristos# Copyright (C) 1994 X Consortium
11*29619d2aSchristos#
12*29619d2aSchristos# Permission is hereby granted, free of charge, to any person obtaining a copy
13*29619d2aSchristos# of this software and associated documentation files (the "Software"), to
14*29619d2aSchristos# deal in the Software without restriction, including without limitation the
15*29619d2aSchristos# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16*29619d2aSchristos# sell copies of the Software, and to permit persons to whom the Software is
17*29619d2aSchristos# furnished to do so, subject to the following conditions:
18*29619d2aSchristos#
19*29619d2aSchristos# The above copyright notice and this permission notice shall be included in
20*29619d2aSchristos# all copies or substantial portions of the Software.
21*29619d2aSchristos#
22*29619d2aSchristos# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23*29619d2aSchristos# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24*29619d2aSchristos# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
25*29619d2aSchristos# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26*29619d2aSchristos# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
27*29619d2aSchristos# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28*29619d2aSchristos#
29*29619d2aSchristos# Except as contained in this notice, the name of the X Consortium shall not
30*29619d2aSchristos# be used in advertising or otherwise to promote the sale, use or other deal-
31*29619d2aSchristos# ings in this Software without prior written authorization from the X Consor-
32*29619d2aSchristos# tium.
33*29619d2aSchristos#
34*29619d2aSchristos#
35*29619d2aSchristos# FSF changes to this file are in the public domain.
36*29619d2aSchristos#
37*29619d2aSchristos# Calling this script install-sh is preferred over install.sh, to prevent
38*29619d2aSchristos# `make' implicit rules from creating a file called install from it
39*29619d2aSchristos# when there is no Makefile.
40*29619d2aSchristos#
41*29619d2aSchristos# This script is compatible with the BSD install script, but was written
42*29619d2aSchristos# from scratch.  It can only install one file at a time, a restriction
43*29619d2aSchristos# shared with many OS's install programs.
44*29619d2aSchristos
45*29619d2aSchristos# set DOITPROG to echo to test this script
46*29619d2aSchristos
47*29619d2aSchristos# Don't use :- since 4.3BSD and earlier shells don't like it.
48*29619d2aSchristosdoit="${DOITPROG-}"
49*29619d2aSchristos
50*29619d2aSchristos# put in absolute paths if you don't have them in your path; or use env. vars.
51*29619d2aSchristos
52*29619d2aSchristosmvprog="${MVPROG-mv}"
53*29619d2aSchristoscpprog="${CPPROG-cp}"
54*29619d2aSchristoschmodprog="${CHMODPROG-chmod}"
55*29619d2aSchristoschownprog="${CHOWNPROG-chown}"
56*29619d2aSchristoschgrpprog="${CHGRPPROG-chgrp}"
57*29619d2aSchristosstripprog="${STRIPPROG-strip}"
58*29619d2aSchristosrmprog="${RMPROG-rm}"
59*29619d2aSchristosmkdirprog="${MKDIRPROG-mkdir}"
60*29619d2aSchristos
61*29619d2aSchristoschmodcmd="$chmodprog 0755"
62*29619d2aSchristoschowncmd=
63*29619d2aSchristoschgrpcmd=
64*29619d2aSchristosstripcmd=
65*29619d2aSchristosrmcmd="$rmprog -f"
66*29619d2aSchristosmvcmd="$mvprog"
67*29619d2aSchristossrc=
68*29619d2aSchristosdst=
69*29619d2aSchristosdir_arg=
70*29619d2aSchristosdstarg=
71*29619d2aSchristosno_target_directory=
72*29619d2aSchristos
73*29619d2aSchristosusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
74*29619d2aSchristos   or: $0 [OPTION]... SRCFILES... DIRECTORY
75*29619d2aSchristos   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
76*29619d2aSchristos   or: $0 [OPTION]... -d DIRECTORIES...
77*29619d2aSchristos
78*29619d2aSchristosIn the 1st form, copy SRCFILE to DSTFILE.
79*29619d2aSchristosIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
80*29619d2aSchristosIn the 4th, create DIRECTORIES.
81*29619d2aSchristos
82*29619d2aSchristosOptions:
83*29619d2aSchristos-c         (ignored)
84*29619d2aSchristos-d         create directories instead of installing files.
85*29619d2aSchristos-g GROUP   $chgrpprog installed files to GROUP.
86*29619d2aSchristos-m MODE    $chmodprog installed files to MODE.
87*29619d2aSchristos-o USER    $chownprog installed files to USER.
88*29619d2aSchristos-s         $stripprog installed files.
89*29619d2aSchristos-t DIRECTORY  install into DIRECTORY.
90*29619d2aSchristos-T         report an error if DSTFILE is a directory.
91*29619d2aSchristos--help     display this help and exit.
92*29619d2aSchristos--version  display version info and exit.
93*29619d2aSchristos
94*29619d2aSchristosEnvironment variables override the default commands:
95*29619d2aSchristos  CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
96*29619d2aSchristos"
97*29619d2aSchristos
98*29619d2aSchristoswhile test -n "$1"; do
99*29619d2aSchristos  case $1 in
100*29619d2aSchristos    -c) shift
101*29619d2aSchristos        continue;;
102*29619d2aSchristos
103*29619d2aSchristos    -d) dir_arg=true
104*29619d2aSchristos        shift
105*29619d2aSchristos        continue;;
106*29619d2aSchristos
107*29619d2aSchristos    -g) chgrpcmd="$chgrpprog $2"
108*29619d2aSchristos        shift
109*29619d2aSchristos        shift
110*29619d2aSchristos        continue;;
111*29619d2aSchristos
112*29619d2aSchristos    --help) echo "$usage"; exit 0;;
113*29619d2aSchristos
114*29619d2aSchristos    -m) chmodcmd="$chmodprog $2"
115*29619d2aSchristos        shift
116*29619d2aSchristos        shift
117*29619d2aSchristos        continue;;
118*29619d2aSchristos
119*29619d2aSchristos    -o) chowncmd="$chownprog $2"
120*29619d2aSchristos        shift
121*29619d2aSchristos        shift
122*29619d2aSchristos        continue;;
123*29619d2aSchristos
124*29619d2aSchristos    -s) stripcmd=$stripprog
125*29619d2aSchristos        shift
126*29619d2aSchristos        continue;;
127*29619d2aSchristos
128*29619d2aSchristos    -t) dstarg=$2
129*29619d2aSchristos	shift
130*29619d2aSchristos	shift
131*29619d2aSchristos	continue;;
132*29619d2aSchristos
133*29619d2aSchristos    -T) no_target_directory=true
134*29619d2aSchristos	shift
135*29619d2aSchristos	continue;;
136*29619d2aSchristos
137*29619d2aSchristos    --version) echo "$0 $scriptversion"; exit 0;;
138*29619d2aSchristos
139*29619d2aSchristos    *)  # When -d is used, all remaining arguments are directories to create.
140*29619d2aSchristos	# When -t is used, the destination is already specified.
141*29619d2aSchristos	test -n "$dir_arg$dstarg" && break
142*29619d2aSchristos        # Otherwise, the last argument is the destination.  Remove it from $@.
143*29619d2aSchristos	for arg
144*29619d2aSchristos	do
145*29619d2aSchristos          if test -n "$dstarg"; then
146*29619d2aSchristos	    # $@ is not empty: it contains at least $arg.
147*29619d2aSchristos	    set fnord "$@" "$dstarg"
148*29619d2aSchristos	    shift # fnord
149*29619d2aSchristos	  fi
150*29619d2aSchristos	  shift # arg
151*29619d2aSchristos	  dstarg=$arg
152*29619d2aSchristos	done
153*29619d2aSchristos	break;;
154*29619d2aSchristos  esac
155*29619d2aSchristosdone
156*29619d2aSchristos
157*29619d2aSchristosif test -z "$1"; then
158*29619d2aSchristos  if test -z "$dir_arg"; then
159*29619d2aSchristos    echo "$0: no input file specified." >&2
160*29619d2aSchristos    exit 1
161*29619d2aSchristos  fi
162*29619d2aSchristos  # It's OK to call `install-sh -d' without argument.
163*29619d2aSchristos  # This can happen when creating conditional directories.
164*29619d2aSchristos  exit 0
165*29619d2aSchristosfi
166*29619d2aSchristos
167*29619d2aSchristosfor src
168*29619d2aSchristosdo
169*29619d2aSchristos  # Protect names starting with `-'.
170*29619d2aSchristos  case $src in
171*29619d2aSchristos    -*) src=./$src ;;
172*29619d2aSchristos  esac
173*29619d2aSchristos
174*29619d2aSchristos  if test -n "$dir_arg"; then
175*29619d2aSchristos    dst=$src
176*29619d2aSchristos    src=
177*29619d2aSchristos
178*29619d2aSchristos    if test -d "$dst"; then
179*29619d2aSchristos      mkdircmd=:
180*29619d2aSchristos      chmodcmd=
181*29619d2aSchristos    else
182*29619d2aSchristos      mkdircmd=$mkdirprog
183*29619d2aSchristos    fi
184*29619d2aSchristos  else
185*29619d2aSchristos    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
186*29619d2aSchristos    # might cause directories to be created, which would be especially bad
187*29619d2aSchristos    # if $src (and thus $dsttmp) contains '*'.
188*29619d2aSchristos    if test ! -f "$src" && test ! -d "$src"; then
189*29619d2aSchristos      echo "$0: $src does not exist." >&2
190*29619d2aSchristos      exit 1
191*29619d2aSchristos    fi
192*29619d2aSchristos
193*29619d2aSchristos    if test -z "$dstarg"; then
194*29619d2aSchristos      echo "$0: no destination specified." >&2
195*29619d2aSchristos      exit 1
196*29619d2aSchristos    fi
197*29619d2aSchristos
198*29619d2aSchristos    dst=$dstarg
199*29619d2aSchristos    # Protect names starting with `-'.
200*29619d2aSchristos    case $dst in
201*29619d2aSchristos      -*) dst=./$dst ;;
202*29619d2aSchristos    esac
203*29619d2aSchristos
204*29619d2aSchristos    # If destination is a directory, append the input filename; won't work
205*29619d2aSchristos    # if double slashes aren't ignored.
206*29619d2aSchristos    if test -d "$dst"; then
207*29619d2aSchristos      if test -n "$no_target_directory"; then
208*29619d2aSchristos	echo "$0: $dstarg: Is a directory" >&2
209*29619d2aSchristos	exit 1
210*29619d2aSchristos      fi
211*29619d2aSchristos      dst=$dst/`basename "$src"`
212*29619d2aSchristos    fi
213*29619d2aSchristos  fi
214*29619d2aSchristos
215*29619d2aSchristos  # This sed command emulates the dirname command.
216*29619d2aSchristos  dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'`
217*29619d2aSchristos
218*29619d2aSchristos  # Make sure that the destination directory exists.
219*29619d2aSchristos
220*29619d2aSchristos  # Skip lots of stat calls in the usual case.
221*29619d2aSchristos  if test ! -d "$dstdir"; then
222*29619d2aSchristos    defaultIFS='
223*29619d2aSchristos	 '
224*29619d2aSchristos    IFS="${IFS-$defaultIFS}"
225*29619d2aSchristos
226*29619d2aSchristos    oIFS=$IFS
227*29619d2aSchristos    # Some sh's can't handle IFS=/ for some reason.
228*29619d2aSchristos    IFS='%'
229*29619d2aSchristos    set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
230*29619d2aSchristos    shift
231*29619d2aSchristos    IFS=$oIFS
232*29619d2aSchristos
233*29619d2aSchristos    pathcomp=
234*29619d2aSchristos
235*29619d2aSchristos    while test $# -ne 0 ; do
236*29619d2aSchristos      pathcomp=$pathcomp$1
237*29619d2aSchristos      shift
238*29619d2aSchristos      if test ! -d "$pathcomp"; then
239*29619d2aSchristos        $mkdirprog "$pathcomp"
240*29619d2aSchristos	# mkdir can fail with a `File exist' error in case several
241*29619d2aSchristos	# install-sh are creating the directory concurrently.  This
242*29619d2aSchristos	# is OK.
243*29619d2aSchristos	test -d "$pathcomp" || exit
244*29619d2aSchristos      fi
245*29619d2aSchristos      pathcomp=$pathcomp/
246*29619d2aSchristos    done
247*29619d2aSchristos  fi
248*29619d2aSchristos
249*29619d2aSchristos  if test -n "$dir_arg"; then
250*29619d2aSchristos    $doit $mkdircmd "$dst" \
251*29619d2aSchristos      && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
252*29619d2aSchristos      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
253*29619d2aSchristos      && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
254*29619d2aSchristos      && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
255*29619d2aSchristos
256*29619d2aSchristos  else
257*29619d2aSchristos    dstfile=`basename "$dst"`
258*29619d2aSchristos
259*29619d2aSchristos    # Make a couple of temp file names in the proper directory.
260*29619d2aSchristos    dsttmp=$dstdir/_inst.$$_
261*29619d2aSchristos    rmtmp=$dstdir/_rm.$$_
262*29619d2aSchristos
263*29619d2aSchristos    # Trap to clean up those temp files at exit.
264*29619d2aSchristos    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
265*29619d2aSchristos    trap '(exit $?); exit' 1 2 13 15
266*29619d2aSchristos
267*29619d2aSchristos    # Copy the file name to the temp name.
268*29619d2aSchristos    $doit $cpprog "$src" "$dsttmp" &&
269*29619d2aSchristos
270*29619d2aSchristos    # and set any options; do chmod last to preserve setuid bits.
271*29619d2aSchristos    #
272*29619d2aSchristos    # If any of these fail, we abort the whole thing.  If we want to
273*29619d2aSchristos    # ignore errors from any of these, just make sure not to ignore
274*29619d2aSchristos    # errors from the above "$doit $cpprog $src $dsttmp" command.
275*29619d2aSchristos    #
276*29619d2aSchristos    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
277*29619d2aSchristos      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
278*29619d2aSchristos      && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
279*29619d2aSchristos      && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
280*29619d2aSchristos
281*29619d2aSchristos    # Now rename the file to the real destination.
282*29619d2aSchristos    { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
283*29619d2aSchristos      || {
284*29619d2aSchristos	   # The rename failed, perhaps because mv can't rename something else
285*29619d2aSchristos	   # to itself, or perhaps because mv is so ancient that it does not
286*29619d2aSchristos	   # support -f.
287*29619d2aSchristos
288*29619d2aSchristos	   # Now remove or move aside any old file at destination location.
289*29619d2aSchristos	   # We try this two ways since rm can't unlink itself on some
290*29619d2aSchristos	   # systems and the destination file might be busy for other
291*29619d2aSchristos	   # reasons.  In this case, the final cleanup might fail but the new
292*29619d2aSchristos	   # file should still install successfully.
293*29619d2aSchristos	   {
294*29619d2aSchristos	     if test -f "$dstdir/$dstfile"; then
295*29619d2aSchristos	       $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
296*29619d2aSchristos	       || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
297*29619d2aSchristos	       || {
298*29619d2aSchristos		 echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
299*29619d2aSchristos		 (exit 1); exit 1
300*29619d2aSchristos	       }
301*29619d2aSchristos	     else
302*29619d2aSchristos	       :
303*29619d2aSchristos	     fi
304*29619d2aSchristos	   } &&
305*29619d2aSchristos
306*29619d2aSchristos	   # Now rename the file to the real destination.
307*29619d2aSchristos	   $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
308*29619d2aSchristos	 }
309*29619d2aSchristos    }
310*29619d2aSchristos  fi || { (exit 1); exit 1; }
311*29619d2aSchristosdone
312*29619d2aSchristos
313*29619d2aSchristos# The final little trick to "correctly" pass the exit status to the exit trap.
314*29619d2aSchristos{
315*29619d2aSchristos  (exit 0); exit 0
316*29619d2aSchristos}
317*29619d2aSchristos
318*29619d2aSchristos# Local variables:
319*29619d2aSchristos# eval: (add-hook 'write-file-hooks 'time-stamp)
320*29619d2aSchristos# time-stamp-start: "scriptversion="
321*29619d2aSchristos# time-stamp-format: "%:y-%02m-%02d.%02H"
322*29619d2aSchristos# time-stamp-end: "$"
323*29619d2aSchristos# End:
324