install-sh revision 174832
1117610Sdes#!/bin/sh
2117610Sdes# install - install a program, script, or datafile
3141098Sdes
4174832Sdesscriptversion=2005-05-14.22
5141098Sdes
6141098Sdes# This originates from X11R5 (mit/util/scripts/install.sh), which was
7141098Sdes# later released in X11R6 (xc/config/util/install.sh) with the
8141098Sdes# following copyright and license.
9117610Sdes#
10141098Sdes# Copyright (C) 1994 X Consortium
11117610Sdes#
12141098Sdes# Permission is hereby granted, free of charge, to any person obtaining a copy
13141098Sdes# of this software and associated documentation files (the "Software"), to
14141098Sdes# deal in the Software without restriction, including without limitation the
15141098Sdes# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16141098Sdes# sell copies of the Software, and to permit persons to whom the Software is
17141098Sdes# furnished to do so, subject to the following conditions:
18117610Sdes#
19141098Sdes# The above copyright notice and this permission notice shall be included in
20141098Sdes# all copies or substantial portions of the Software.
21141098Sdes#
22141098Sdes# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23141098Sdes# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24141098Sdes# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
25141098Sdes# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26141098Sdes# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
27141098Sdes# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28141098Sdes#
29141098Sdes# Except as contained in this notice, the name of the X Consortium shall not
30141098Sdes# be used in advertising or otherwise to promote the sale, use or other deal-
31141098Sdes# ings in this Software without prior written authorization from the X Consor-
32141098Sdes# tium.
33141098Sdes#
34141098Sdes#
35141098Sdes# FSF changes to this file are in the public domain.
36141098Sdes#
37117610Sdes# Calling this script install-sh is preferred over install.sh, to prevent
38117610Sdes# `make' implicit rules from creating a file called install from it
39117610Sdes# when there is no Makefile.
40117610Sdes#
41117610Sdes# This script is compatible with the BSD install script, but was written
42117610Sdes# from scratch.  It can only install one file at a time, a restriction
43117610Sdes# shared with many OS's install programs.
44117610Sdes
45117610Sdes# set DOITPROG to echo to test this script
46117610Sdes
47117610Sdes# Don't use :- since 4.3BSD and earlier shells don't like it.
48117610Sdesdoit="${DOITPROG-}"
49117610Sdes
50117610Sdes# put in absolute paths if you don't have them in your path; or use env. vars.
51117610Sdes
52117610Sdesmvprog="${MVPROG-mv}"
53117610Sdescpprog="${CPPROG-cp}"
54117610Sdeschmodprog="${CHMODPROG-chmod}"
55117610Sdeschownprog="${CHOWNPROG-chown}"
56117610Sdeschgrpprog="${CHGRPPROG-chgrp}"
57117610Sdesstripprog="${STRIPPROG-strip}"
58117610Sdesrmprog="${RMPROG-rm}"
59117610Sdesmkdirprog="${MKDIRPROG-mkdir}"
60117610Sdes
61117610Sdeschmodcmd="$chmodprog 0755"
62141098Sdeschowncmd=
63141098Sdeschgrpcmd=
64141098Sdesstripcmd=
65117610Sdesrmcmd="$rmprog -f"
66117610Sdesmvcmd="$mvprog"
67141098Sdessrc=
68141098Sdesdst=
69141098Sdesdir_arg=
70174832Sdesdstarg=
71174832Sdesno_target_directory=
72117610Sdes
73174832Sdesusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
74141098Sdes   or: $0 [OPTION]... SRCFILES... DIRECTORY
75174832Sdes   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
76174832Sdes   or: $0 [OPTION]... -d DIRECTORIES...
77117610Sdes
78174832SdesIn the 1st form, copy SRCFILE to DSTFILE.
79174832SdesIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
80174832SdesIn the 4th, create DIRECTORIES.
81117610Sdes
82141098SdesOptions:
83174832Sdes-c         (ignored)
84141098Sdes-d         create directories instead of installing files.
85174832Sdes-g GROUP   $chgrpprog installed files to GROUP.
86174832Sdes-m MODE    $chmodprog installed files to MODE.
87174832Sdes-o USER    $chownprog installed files to USER.
88174832Sdes-s         $stripprog installed files.
89174832Sdes-t DIRECTORY  install into DIRECTORY.
90174832Sdes-T         report an error if DSTFILE is a directory.
91141098Sdes--help     display this help and exit.
92141098Sdes--version  display version info and exit.
93117610Sdes
94141098SdesEnvironment variables override the default commands:
95141098Sdes  CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
96141098Sdes"
97117610Sdes
98141098Sdeswhile test -n "$1"; do
99141098Sdes  case $1 in
100174832Sdes    -c) shift
101141098Sdes        continue;;
102117610Sdes
103141098Sdes    -d) dir_arg=true
104141098Sdes        shift
105141098Sdes        continue;;
106117610Sdes
107141098Sdes    -g) chgrpcmd="$chgrpprog $2"
108141098Sdes        shift
109141098Sdes        shift
110141098Sdes        continue;;
111117610Sdes
112174832Sdes    --help) echo "$usage"; exit $?;;
113117610Sdes
114141098Sdes    -m) chmodcmd="$chmodprog $2"
115141098Sdes        shift
116141098Sdes        shift
117141098Sdes        continue;;
118117610Sdes
119141098Sdes    -o) chowncmd="$chownprog $2"
120141098Sdes        shift
121141098Sdes        shift
122141098Sdes        continue;;
123117610Sdes
124141098Sdes    -s) stripcmd=$stripprog
125141098Sdes        shift
126141098Sdes        continue;;
127117610Sdes
128174832Sdes    -t) dstarg=$2
129174832Sdes	shift
130174832Sdes	shift
131174832Sdes	continue;;
132117610Sdes
133174832Sdes    -T) no_target_directory=true
134174832Sdes	shift
135174832Sdes	continue;;
136117610Sdes
137174832Sdes    --version) echo "$0 $scriptversion"; exit $?;;
138174832Sdes
139141098Sdes    *)  # When -d is used, all remaining arguments are directories to create.
140174832Sdes	# When -t is used, the destination is already specified.
141174832Sdes	test -n "$dir_arg$dstarg" && break
142141098Sdes        # Otherwise, the last argument is the destination.  Remove it from $@.
143141098Sdes	for arg
144141098Sdes	do
145141098Sdes          if test -n "$dstarg"; then
146141098Sdes	    # $@ is not empty: it contains at least $arg.
147141098Sdes	    set fnord "$@" "$dstarg"
148141098Sdes	    shift # fnord
149141098Sdes	  fi
150141098Sdes	  shift # arg
151141098Sdes	  dstarg=$arg
152141098Sdes	done
153141098Sdes	break;;
154141098Sdes  esac
155141098Sdesdone
156141098Sdes
157141098Sdesif test -z "$1"; then
158141098Sdes  if test -z "$dir_arg"; then
159141098Sdes    echo "$0: no input file specified." >&2
160141098Sdes    exit 1
161141098Sdes  fi
162141098Sdes  # It's OK to call `install-sh -d' without argument.
163141098Sdes  # This can happen when creating conditional directories.
164141098Sdes  exit 0
165117610Sdesfi
166117610Sdes
167141098Sdesfor src
168141098Sdesdo
169141098Sdes  # Protect names starting with `-'.
170141098Sdes  case $src in
171141098Sdes    -*) src=./$src ;;
172141098Sdes  esac
173117610Sdes
174141098Sdes  if test -n "$dir_arg"; then
175141098Sdes    dst=$src
176141098Sdes    src=
177117610Sdes
178141098Sdes    if test -d "$dst"; then
179174832Sdes      mkdircmd=:
180141098Sdes      chmodcmd=
181141098Sdes    else
182174832Sdes      mkdircmd=$mkdirprog
183141098Sdes    fi
184141098Sdes  else
185174832Sdes    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
186141098Sdes    # might cause directories to be created, which would be especially bad
187141098Sdes    # if $src (and thus $dsttmp) contains '*'.
188141098Sdes    if test ! -f "$src" && test ! -d "$src"; then
189141098Sdes      echo "$0: $src does not exist." >&2
190141098Sdes      exit 1
191141098Sdes    fi
192117610Sdes
193141098Sdes    if test -z "$dstarg"; then
194141098Sdes      echo "$0: no destination specified." >&2
195141098Sdes      exit 1
196141098Sdes    fi
197117610Sdes
198141098Sdes    dst=$dstarg
199141098Sdes    # Protect names starting with `-'.
200141098Sdes    case $dst in
201141098Sdes      -*) dst=./$dst ;;
202141098Sdes    esac
203117610Sdes
204141098Sdes    # If destination is a directory, append the input filename; won't work
205141098Sdes    # if double slashes aren't ignored.
206141098Sdes    if test -d "$dst"; then
207174832Sdes      if test -n "$no_target_directory"; then
208174832Sdes	echo "$0: $dstarg: Is a directory" >&2
209174832Sdes	exit 1
210174832Sdes      fi
211141098Sdes      dst=$dst/`basename "$src"`
212141098Sdes    fi
213141098Sdes  fi
214117610Sdes
215141098Sdes  # This sed command emulates the dirname command.
216174832Sdes  dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'`
217117610Sdes
218141098Sdes  # Make sure that the destination directory exists.
219117610Sdes
220141098Sdes  # Skip lots of stat calls in the usual case.
221141098Sdes  if test ! -d "$dstdir"; then
222141098Sdes    defaultIFS='
223141098Sdes	 '
224141098Sdes    IFS="${IFS-$defaultIFS}"
225117610Sdes
226141098Sdes    oIFS=$IFS
227141098Sdes    # Some sh's can't handle IFS=/ for some reason.
228141098Sdes    IFS='%'
229174832Sdes    set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
230174832Sdes    shift
231141098Sdes    IFS=$oIFS
232117610Sdes
233141098Sdes    pathcomp=
234117610Sdes
235141098Sdes    while test $# -ne 0 ; do
236141098Sdes      pathcomp=$pathcomp$1
237141098Sdes      shift
238141098Sdes      if test ! -d "$pathcomp"; then
239174832Sdes        $mkdirprog "$pathcomp"
240141098Sdes	# mkdir can fail with a `File exist' error in case several
241141098Sdes	# install-sh are creating the directory concurrently.  This
242141098Sdes	# is OK.
243174832Sdes	test -d "$pathcomp" || exit
244141098Sdes      fi
245141098Sdes      pathcomp=$pathcomp/
246141098Sdes    done
247141098Sdes  fi
248117610Sdes
249141098Sdes  if test -n "$dir_arg"; then
250174832Sdes    $doit $mkdircmd "$dst" \
251141098Sdes      && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
252141098Sdes      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
253141098Sdes      && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
254141098Sdes      && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
255117610Sdes
256141098Sdes  else
257174832Sdes    dstfile=`basename "$dst"`
258117610Sdes
259141098Sdes    # Make a couple of temp file names in the proper directory.
260141098Sdes    dsttmp=$dstdir/_inst.$$_
261141098Sdes    rmtmp=$dstdir/_rm.$$_
262117610Sdes
263141098Sdes    # Trap to clean up those temp files at exit.
264174832Sdes    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
265141098Sdes    trap '(exit $?); exit' 1 2 13 15
266117610Sdes
267174832Sdes    # Copy the file name to the temp name.
268174832Sdes    $doit $cpprog "$src" "$dsttmp" &&
269117610Sdes
270141098Sdes    # and set any options; do chmod last to preserve setuid bits.
271141098Sdes    #
272141098Sdes    # If any of these fail, we abort the whole thing.  If we want to
273141098Sdes    # ignore errors from any of these, just make sure not to ignore
274174832Sdes    # errors from the above "$doit $cpprog $src $dsttmp" command.
275141098Sdes    #
276141098Sdes    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
277141098Sdes      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
278141098Sdes      && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
279141098Sdes      && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
280117610Sdes
281141098Sdes    # Now rename the file to the real destination.
282141098Sdes    { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
283141098Sdes      || {
284141098Sdes	   # The rename failed, perhaps because mv can't rename something else
285141098Sdes	   # to itself, or perhaps because mv is so ancient that it does not
286141098Sdes	   # support -f.
287117610Sdes
288141098Sdes	   # Now remove or move aside any old file at destination location.
289141098Sdes	   # We try this two ways since rm can't unlink itself on some
290141098Sdes	   # systems and the destination file might be busy for other
291141098Sdes	   # reasons.  In this case, the final cleanup might fail but the new
292141098Sdes	   # file should still install successfully.
293141098Sdes	   {
294141098Sdes	     if test -f "$dstdir/$dstfile"; then
295141098Sdes	       $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
296141098Sdes	       || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
297141098Sdes	       || {
298141098Sdes		 echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
299174832Sdes		 (exit 1); exit 1
300141098Sdes	       }
301141098Sdes	     else
302141098Sdes	       :
303141098Sdes	     fi
304141098Sdes	   } &&
305117610Sdes
306141098Sdes	   # Now rename the file to the real destination.
307141098Sdes	   $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
308141098Sdes	 }
309141098Sdes    }
310174832Sdes  fi || { (exit 1); exit 1; }
311141098Sdesdone
312117610Sdes
313141098Sdes# The final little trick to "correctly" pass the exit status to the exit trap.
314141098Sdes{
315174832Sdes  (exit 0); exit 0
316141098Sdes}
317117610Sdes
318141098Sdes# Local variables:
319141098Sdes# eval: (add-hook 'write-file-hooks 'time-stamp)
320141098Sdes# time-stamp-start: "scriptversion="
321141098Sdes# time-stamp-format: "%:y-%02m-%02d.%02H"
322141098Sdes# time-stamp-end: "$"
323141098Sdes# End:
324