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