1219820Sjeff#!/bin/sh
2219820Sjeff# install - install a program, script, or datafile
3219820Sjeff
4219820Sjeffscriptversion=2005-05-14.22
5219820Sjeff
6219820Sjeff# This originates from X11R5 (mit/util/scripts/install.sh), which was
7219820Sjeff# later released in X11R6 (xc/config/util/install.sh) with the
8219820Sjeff# following copyright and license.
9219820Sjeff#
10219820Sjeff# Copyright (C) 1994 X Consortium
11219820Sjeff#
12219820Sjeff# Permission is hereby granted, free of charge, to any person obtaining a copy
13219820Sjeff# of this software and associated documentation files (the "Software"), to
14219820Sjeff# deal in the Software without restriction, including without limitation the
15219820Sjeff# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16219820Sjeff# sell copies of the Software, and to permit persons to whom the Software is
17219820Sjeff# furnished to do so, subject to the following conditions:
18219820Sjeff#
19219820Sjeff# The above copyright notice and this permission notice shall be included in
20219820Sjeff# all copies or substantial portions of the Software.
21219820Sjeff#
22219820Sjeff# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23219820Sjeff# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24219820Sjeff# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
25219820Sjeff# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26219820Sjeff# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
27219820Sjeff# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28219820Sjeff#
29219820Sjeff# Except as contained in this notice, the name of the X Consortium shall not
30219820Sjeff# be used in advertising or otherwise to promote the sale, use or other deal-
31219820Sjeff# ings in this Software without prior written authorization from the X Consor-
32219820Sjeff# tium.
33219820Sjeff#
34219820Sjeff#
35219820Sjeff# FSF changes to this file are in the public domain.
36219820Sjeff#
37219820Sjeff# Calling this script install-sh is preferred over install.sh, to prevent
38219820Sjeff# `make' implicit rules from creating a file called install from it
39219820Sjeff# when there is no Makefile.
40219820Sjeff#
41219820Sjeff# This script is compatible with the BSD install script, but was written
42219820Sjeff# from scratch.  It can only install one file at a time, a restriction
43219820Sjeff# shared with many OS's install programs.
44219820Sjeff
45219820Sjeff# set DOITPROG to echo to test this script
46219820Sjeff
47219820Sjeff# Don't use :- since 4.3BSD and earlier shells don't like it.
48219820Sjeffdoit="${DOITPROG-}"
49219820Sjeff
50219820Sjeff# put in absolute paths if you don't have them in your path; or use env. vars.
51219820Sjeff
52219820Sjeffmvprog="${MVPROG-mv}"
53219820Sjeffcpprog="${CPPROG-cp}"
54219820Sjeffchmodprog="${CHMODPROG-chmod}"
55219820Sjeffchownprog="${CHOWNPROG-chown}"
56219820Sjeffchgrpprog="${CHGRPPROG-chgrp}"
57219820Sjeffstripprog="${STRIPPROG-strip}"
58219820Sjeffrmprog="${RMPROG-rm}"
59219820Sjeffmkdirprog="${MKDIRPROG-mkdir}"
60219820Sjeff
61219820Sjeffchmodcmd="$chmodprog 0755"
62219820Sjeffchowncmd=
63219820Sjeffchgrpcmd=
64219820Sjeffstripcmd=
65219820Sjeffrmcmd="$rmprog -f"
66219820Sjeffmvcmd="$mvprog"
67219820Sjeffsrc=
68219820Sjeffdst=
69219820Sjeffdir_arg=
70219820Sjeffdstarg=
71219820Sjeffno_target_directory=
72219820Sjeff
73219820Sjeffusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
74219820Sjeff   or: $0 [OPTION]... SRCFILES... DIRECTORY
75219820Sjeff   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
76219820Sjeff   or: $0 [OPTION]... -d DIRECTORIES...
77219820Sjeff
78219820SjeffIn the 1st form, copy SRCFILE to DSTFILE.
79219820SjeffIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
80219820SjeffIn the 4th, create DIRECTORIES.
81219820Sjeff
82219820SjeffOptions:
83219820Sjeff-c         (ignored)
84219820Sjeff-d         create directories instead of installing files.
85219820Sjeff-g GROUP   $chgrpprog installed files to GROUP.
86219820Sjeff-m MODE    $chmodprog installed files to MODE.
87219820Sjeff-o USER    $chownprog installed files to USER.
88219820Sjeff-s         $stripprog installed files.
89219820Sjeff-t DIRECTORY  install into DIRECTORY.
90219820Sjeff-T         report an error if DSTFILE is a directory.
91219820Sjeff--help     display this help and exit.
92219820Sjeff--version  display version info and exit.
93219820Sjeff
94219820SjeffEnvironment variables override the default commands:
95219820Sjeff  CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
96219820Sjeff"
97219820Sjeff
98219820Sjeffwhile test -n "$1"; do
99219820Sjeff  case $1 in
100219820Sjeff    -c) shift
101219820Sjeff        continue;;
102219820Sjeff
103219820Sjeff    -d) dir_arg=true
104219820Sjeff        shift
105219820Sjeff        continue;;
106219820Sjeff
107219820Sjeff    -g) chgrpcmd="$chgrpprog $2"
108219820Sjeff        shift
109219820Sjeff        shift
110219820Sjeff        continue;;
111219820Sjeff
112219820Sjeff    --help) echo "$usage"; exit $?;;
113219820Sjeff
114219820Sjeff    -m) chmodcmd="$chmodprog $2"
115219820Sjeff        shift
116219820Sjeff        shift
117219820Sjeff        continue;;
118219820Sjeff
119219820Sjeff    -o) chowncmd="$chownprog $2"
120219820Sjeff        shift
121219820Sjeff        shift
122219820Sjeff        continue;;
123219820Sjeff
124219820Sjeff    -s) stripcmd=$stripprog
125219820Sjeff        shift
126219820Sjeff        continue;;
127219820Sjeff
128219820Sjeff    -t) dstarg=$2
129219820Sjeff	shift
130219820Sjeff	shift
131219820Sjeff	continue;;
132219820Sjeff
133219820Sjeff    -T) no_target_directory=true
134219820Sjeff	shift
135219820Sjeff	continue;;
136219820Sjeff
137219820Sjeff    --version) echo "$0 $scriptversion"; exit $?;;
138219820Sjeff
139219820Sjeff    *)  # When -d is used, all remaining arguments are directories to create.
140219820Sjeff	# When -t is used, the destination is already specified.
141219820Sjeff	test -n "$dir_arg$dstarg" && break
142219820Sjeff        # Otherwise, the last argument is the destination.  Remove it from $@.
143219820Sjeff	for arg
144219820Sjeff	do
145219820Sjeff          if test -n "$dstarg"; then
146219820Sjeff	    # $@ is not empty: it contains at least $arg.
147219820Sjeff	    set fnord "$@" "$dstarg"
148219820Sjeff	    shift # fnord
149219820Sjeff	  fi
150219820Sjeff	  shift # arg
151219820Sjeff	  dstarg=$arg
152219820Sjeff	done
153219820Sjeff	break;;
154219820Sjeff  esac
155219820Sjeffdone
156219820Sjeff
157219820Sjeffif test -z "$1"; then
158219820Sjeff  if test -z "$dir_arg"; then
159219820Sjeff    echo "$0: no input file specified." >&2
160219820Sjeff    exit 1
161219820Sjeff  fi
162219820Sjeff  # It's OK to call `install-sh -d' without argument.
163219820Sjeff  # This can happen when creating conditional directories.
164219820Sjeff  exit 0
165219820Sjefffi
166219820Sjeff
167219820Sjefffor src
168219820Sjeffdo
169219820Sjeff  # Protect names starting with `-'.
170219820Sjeff  case $src in
171219820Sjeff    -*) src=./$src ;;
172219820Sjeff  esac
173219820Sjeff
174219820Sjeff  if test -n "$dir_arg"; then
175219820Sjeff    dst=$src
176219820Sjeff    src=
177219820Sjeff
178219820Sjeff    if test -d "$dst"; then
179219820Sjeff      mkdircmd=:
180219820Sjeff      chmodcmd=
181219820Sjeff    else
182219820Sjeff      mkdircmd=$mkdirprog
183219820Sjeff    fi
184219820Sjeff  else
185219820Sjeff    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
186219820Sjeff    # might cause directories to be created, which would be especially bad
187219820Sjeff    # if $src (and thus $dsttmp) contains '*'.
188219820Sjeff    if test ! -f "$src" && test ! -d "$src"; then
189219820Sjeff      echo "$0: $src does not exist." >&2
190219820Sjeff      exit 1
191219820Sjeff    fi
192219820Sjeff
193219820Sjeff    if test -z "$dstarg"; then
194219820Sjeff      echo "$0: no destination specified." >&2
195219820Sjeff      exit 1
196219820Sjeff    fi
197219820Sjeff
198219820Sjeff    dst=$dstarg
199219820Sjeff    # Protect names starting with `-'.
200219820Sjeff    case $dst in
201219820Sjeff      -*) dst=./$dst ;;
202219820Sjeff    esac
203219820Sjeff
204219820Sjeff    # If destination is a directory, append the input filename; won't work
205219820Sjeff    # if double slashes aren't ignored.
206219820Sjeff    if test -d "$dst"; then
207219820Sjeff      if test -n "$no_target_directory"; then
208219820Sjeff	echo "$0: $dstarg: Is a directory" >&2
209219820Sjeff	exit 1
210219820Sjeff      fi
211219820Sjeff      dst=$dst/`basename "$src"`
212219820Sjeff    fi
213219820Sjeff  fi
214219820Sjeff
215219820Sjeff  # This sed command emulates the dirname command.
216219820Sjeff  dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'`
217219820Sjeff
218219820Sjeff  # Make sure that the destination directory exists.
219219820Sjeff
220219820Sjeff  # Skip lots of stat calls in the usual case.
221219820Sjeff  if test ! -d "$dstdir"; then
222219820Sjeff    defaultIFS='
223219820Sjeff	 '
224219820Sjeff    IFS="${IFS-$defaultIFS}"
225219820Sjeff
226219820Sjeff    oIFS=$IFS
227219820Sjeff    # Some sh's can't handle IFS=/ for some reason.
228219820Sjeff    IFS='%'
229219820Sjeff    set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
230219820Sjeff    shift
231219820Sjeff    IFS=$oIFS
232219820Sjeff
233219820Sjeff    pathcomp=
234219820Sjeff
235219820Sjeff    while test $# -ne 0 ; do
236219820Sjeff      pathcomp=$pathcomp$1
237219820Sjeff      shift
238219820Sjeff      if test ! -d "$pathcomp"; then
239219820Sjeff        $mkdirprog "$pathcomp"
240219820Sjeff	# mkdir can fail with a `File exist' error in case several
241219820Sjeff	# install-sh are creating the directory concurrently.  This
242219820Sjeff	# is OK.
243219820Sjeff	test -d "$pathcomp" || exit
244219820Sjeff      fi
245219820Sjeff      pathcomp=$pathcomp/
246219820Sjeff    done
247219820Sjeff  fi
248219820Sjeff
249219820Sjeff  if test -n "$dir_arg"; then
250219820Sjeff    $doit $mkdircmd "$dst" \
251219820Sjeff      && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
252219820Sjeff      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
253219820Sjeff      && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
254219820Sjeff      && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
255219820Sjeff
256219820Sjeff  else
257219820Sjeff    dstfile=`basename "$dst"`
258219820Sjeff
259219820Sjeff    # Make a couple of temp file names in the proper directory.
260219820Sjeff    dsttmp=$dstdir/_inst.$$_
261219820Sjeff    rmtmp=$dstdir/_rm.$$_
262219820Sjeff
263219820Sjeff    # Trap to clean up those temp files at exit.
264219820Sjeff    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
265219820Sjeff    trap '(exit $?); exit' 1 2 13 15
266219820Sjeff
267219820Sjeff    # Copy the file name to the temp name.
268219820Sjeff    $doit $cpprog "$src" "$dsttmp" &&
269219820Sjeff
270219820Sjeff    # and set any options; do chmod last to preserve setuid bits.
271219820Sjeff    #
272219820Sjeff    # If any of these fail, we abort the whole thing.  If we want to
273219820Sjeff    # ignore errors from any of these, just make sure not to ignore
274219820Sjeff    # errors from the above "$doit $cpprog $src $dsttmp" command.
275219820Sjeff    #
276219820Sjeff    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
277219820Sjeff      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
278219820Sjeff      && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
279219820Sjeff      && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
280219820Sjeff
281219820Sjeff    # Now rename the file to the real destination.
282219820Sjeff    { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
283219820Sjeff      || {
284219820Sjeff	   # The rename failed, perhaps because mv can't rename something else
285219820Sjeff	   # to itself, or perhaps because mv is so ancient that it does not
286219820Sjeff	   # support -f.
287219820Sjeff
288219820Sjeff	   # Now remove or move aside any old file at destination location.
289219820Sjeff	   # We try this two ways since rm can't unlink itself on some
290219820Sjeff	   # systems and the destination file might be busy for other
291219820Sjeff	   # reasons.  In this case, the final cleanup might fail but the new
292219820Sjeff	   # file should still install successfully.
293219820Sjeff	   {
294219820Sjeff	     if test -f "$dstdir/$dstfile"; then
295219820Sjeff	       $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
296219820Sjeff	       || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
297219820Sjeff	       || {
298219820Sjeff		 echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
299219820Sjeff		 (exit 1); exit 1
300219820Sjeff	       }
301219820Sjeff	     else
302219820Sjeff	       :
303219820Sjeff	     fi
304219820Sjeff	   } &&
305219820Sjeff
306219820Sjeff	   # Now rename the file to the real destination.
307219820Sjeff	   $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
308219820Sjeff	 }
309219820Sjeff    }
310219820Sjeff  fi || { (exit 1); exit 1; }
311219820Sjeffdone
312219820Sjeff
313219820Sjeff# The final little trick to "correctly" pass the exit status to the exit trap.
314219820Sjeff{
315219820Sjeff  (exit 0); exit 0
316219820Sjeff}
317219820Sjeff
318219820Sjeff# Local variables:
319219820Sjeff# eval: (add-hook 'write-file-hooks 'time-stamp)
320219820Sjeff# time-stamp-start: "scriptversion="
321219820Sjeff# time-stamp-format: "%:y-%02m-%02d.%02H"
322219820Sjeff# time-stamp-end: "$"
323219820Sjeff# End:
324