1240a9a23Smbalmer#!/bin/sh
2240a9a23Smbalmer# install - install a program, script, or datafile
3240a9a23Smbalmer
4240a9a23Smbalmerscriptversion=2005-05-14.22
5240a9a23Smbalmer
6240a9a23Smbalmer# This originates from X11R5 (mit/util/scripts/install.sh), which was
7240a9a23Smbalmer# later released in X11R6 (xc/config/util/install.sh) with the
8240a9a23Smbalmer# following copyright and license.
9240a9a23Smbalmer#
10240a9a23Smbalmer# Copyright (C) 1994 X Consortium
11240a9a23Smbalmer#
12240a9a23Smbalmer# Permission is hereby granted, free of charge, to any person obtaining a copy
13240a9a23Smbalmer# of this software and associated documentation files (the "Software"), to
14240a9a23Smbalmer# deal in the Software without restriction, including without limitation the
15240a9a23Smbalmer# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16240a9a23Smbalmer# sell copies of the Software, and to permit persons to whom the Software is
17240a9a23Smbalmer# furnished to do so, subject to the following conditions:
18240a9a23Smbalmer#
19240a9a23Smbalmer# The above copyright notice and this permission notice shall be included in
20240a9a23Smbalmer# all copies or substantial portions of the Software.
21240a9a23Smbalmer#
22240a9a23Smbalmer# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23240a9a23Smbalmer# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24240a9a23Smbalmer# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
25240a9a23Smbalmer# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26240a9a23Smbalmer# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
27240a9a23Smbalmer# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28240a9a23Smbalmer#
29240a9a23Smbalmer# Except as contained in this notice, the name of the X Consortium shall not
30240a9a23Smbalmer# be used in advertising or otherwise to promote the sale, use or other deal-
31240a9a23Smbalmer# ings in this Software without prior written authorization from the X Consor-
32240a9a23Smbalmer# tium.
33240a9a23Smbalmer#
34240a9a23Smbalmer#
35240a9a23Smbalmer# FSF changes to this file are in the public domain.
36240a9a23Smbalmer#
37240a9a23Smbalmer# Calling this script install-sh is preferred over install.sh, to prevent
38240a9a23Smbalmer# `make' implicit rules from creating a file called install from it
39240a9a23Smbalmer# when there is no Makefile.
40240a9a23Smbalmer#
41240a9a23Smbalmer# This script is compatible with the BSD install script, but was written
42240a9a23Smbalmer# from scratch.  It can only install one file at a time, a restriction
43240a9a23Smbalmer# shared with many OS's install programs.
44240a9a23Smbalmer
45240a9a23Smbalmer# set DOITPROG to echo to test this script
46240a9a23Smbalmer
47240a9a23Smbalmer# Don't use :- since 4.3BSD and earlier shells don't like it.
48240a9a23Smbalmerdoit="${DOITPROG-}"
49240a9a23Smbalmer
50240a9a23Smbalmer# put in absolute paths if you don't have them in your path; or use env. vars.
51240a9a23Smbalmer
52240a9a23Smbalmermvprog="${MVPROG-mv}"
53240a9a23Smbalmercpprog="${CPPROG-cp}"
54240a9a23Smbalmerchmodprog="${CHMODPROG-chmod}"
55240a9a23Smbalmerchownprog="${CHOWNPROG-chown}"
56240a9a23Smbalmerchgrpprog="${CHGRPPROG-chgrp}"
57240a9a23Smbalmerstripprog="${STRIPPROG-strip}"
58240a9a23Smbalmerrmprog="${RMPROG-rm}"
59240a9a23Smbalmermkdirprog="${MKDIRPROG-mkdir}"
60240a9a23Smbalmer
61240a9a23Smbalmerchmodcmd="$chmodprog 0755"
62240a9a23Smbalmerchowncmd=
63240a9a23Smbalmerchgrpcmd=
64240a9a23Smbalmerstripcmd=
65240a9a23Smbalmerrmcmd="$rmprog -f"
66240a9a23Smbalmermvcmd="$mvprog"
67240a9a23Smbalmersrc=
68240a9a23Smbalmerdst=
69240a9a23Smbalmerdir_arg=
70240a9a23Smbalmerdstarg=
71240a9a23Smbalmerno_target_directory=
72240a9a23Smbalmer
73240a9a23Smbalmerusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
74240a9a23Smbalmer   or: $0 [OPTION]... SRCFILES... DIRECTORY
75240a9a23Smbalmer   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
76240a9a23Smbalmer   or: $0 [OPTION]... -d DIRECTORIES...
77240a9a23Smbalmer
78240a9a23SmbalmerIn the 1st form, copy SRCFILE to DSTFILE.
79240a9a23SmbalmerIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
80240a9a23SmbalmerIn the 4th, create DIRECTORIES.
81240a9a23Smbalmer
82240a9a23SmbalmerOptions:
83240a9a23Smbalmer-c         (ignored)
84240a9a23Smbalmer-d         create directories instead of installing files.
85240a9a23Smbalmer-g GROUP   $chgrpprog installed files to GROUP.
86240a9a23Smbalmer-m MODE    $chmodprog installed files to MODE.
87240a9a23Smbalmer-o USER    $chownprog installed files to USER.
88240a9a23Smbalmer-s         $stripprog installed files.
89240a9a23Smbalmer-t DIRECTORY  install into DIRECTORY.
90240a9a23Smbalmer-T         report an error if DSTFILE is a directory.
91240a9a23Smbalmer--help     display this help and exit.
92240a9a23Smbalmer--version  display version info and exit.
93240a9a23Smbalmer
94240a9a23SmbalmerEnvironment variables override the default commands:
95240a9a23Smbalmer  CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
96240a9a23Smbalmer"
97240a9a23Smbalmer
98240a9a23Smbalmerwhile test -n "$1"; do
99240a9a23Smbalmer  case $1 in
100240a9a23Smbalmer    -c) shift
101240a9a23Smbalmer        continue;;
102240a9a23Smbalmer
103240a9a23Smbalmer    -d) dir_arg=true
104240a9a23Smbalmer        shift
105240a9a23Smbalmer        continue;;
106240a9a23Smbalmer
107240a9a23Smbalmer    -g) chgrpcmd="$chgrpprog $2"
108240a9a23Smbalmer        shift
109240a9a23Smbalmer        shift
110240a9a23Smbalmer        continue;;
111240a9a23Smbalmer
112240a9a23Smbalmer    --help) echo "$usage"; exit $?;;
113240a9a23Smbalmer
114240a9a23Smbalmer    -m) chmodcmd="$chmodprog $2"
115240a9a23Smbalmer        shift
116240a9a23Smbalmer        shift
117240a9a23Smbalmer        continue;;
118240a9a23Smbalmer
119240a9a23Smbalmer    -o) chowncmd="$chownprog $2"
120240a9a23Smbalmer        shift
121240a9a23Smbalmer        shift
122240a9a23Smbalmer        continue;;
123240a9a23Smbalmer
124240a9a23Smbalmer    -s) stripcmd=$stripprog
125240a9a23Smbalmer        shift
126240a9a23Smbalmer        continue;;
127240a9a23Smbalmer
128240a9a23Smbalmer    -t) dstarg=$2
129240a9a23Smbalmer	shift
130240a9a23Smbalmer	shift
131240a9a23Smbalmer	continue;;
132240a9a23Smbalmer
133240a9a23Smbalmer    -T) no_target_directory=true
134240a9a23Smbalmer	shift
135240a9a23Smbalmer	continue;;
136240a9a23Smbalmer
137240a9a23Smbalmer    --version) echo "$0 $scriptversion"; exit $?;;
138240a9a23Smbalmer
139240a9a23Smbalmer    *)  # When -d is used, all remaining arguments are directories to create.
140240a9a23Smbalmer	# When -t is used, the destination is already specified.
141240a9a23Smbalmer	test -n "$dir_arg$dstarg" && break
142240a9a23Smbalmer        # Otherwise, the last argument is the destination.  Remove it from $@.
143240a9a23Smbalmer	for arg
144240a9a23Smbalmer	do
145240a9a23Smbalmer          if test -n "$dstarg"; then
146240a9a23Smbalmer	    # $@ is not empty: it contains at least $arg.
147240a9a23Smbalmer	    set fnord "$@" "$dstarg"
148240a9a23Smbalmer	    shift # fnord
149240a9a23Smbalmer	  fi
150240a9a23Smbalmer	  shift # arg
151240a9a23Smbalmer	  dstarg=$arg
152240a9a23Smbalmer	done
153240a9a23Smbalmer	break;;
154240a9a23Smbalmer  esac
155240a9a23Smbalmerdone
156240a9a23Smbalmer
157240a9a23Smbalmerif test -z "$1"; then
158240a9a23Smbalmer  if test -z "$dir_arg"; then
159240a9a23Smbalmer    echo "$0: no input file specified." >&2
160240a9a23Smbalmer    exit 1
161240a9a23Smbalmer  fi
162240a9a23Smbalmer  # It's OK to call `install-sh -d' without argument.
163240a9a23Smbalmer  # This can happen when creating conditional directories.
164240a9a23Smbalmer  exit 0
165240a9a23Smbalmerfi
166240a9a23Smbalmer
167240a9a23Smbalmerfor src
168240a9a23Smbalmerdo
169240a9a23Smbalmer  # Protect names starting with `-'.
170240a9a23Smbalmer  case $src in
171240a9a23Smbalmer    -*) src=./$src ;;
172240a9a23Smbalmer  esac
173240a9a23Smbalmer
174240a9a23Smbalmer  if test -n "$dir_arg"; then
175240a9a23Smbalmer    dst=$src
176240a9a23Smbalmer    src=
177240a9a23Smbalmer
178240a9a23Smbalmer    if test -d "$dst"; then
179240a9a23Smbalmer      mkdircmd=:
180240a9a23Smbalmer      chmodcmd=
181240a9a23Smbalmer    else
182240a9a23Smbalmer      mkdircmd=$mkdirprog
183240a9a23Smbalmer    fi
184240a9a23Smbalmer  else
185240a9a23Smbalmer    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
186240a9a23Smbalmer    # might cause directories to be created, which would be especially bad
187240a9a23Smbalmer    # if $src (and thus $dsttmp) contains '*'.
188240a9a23Smbalmer    if test ! -f "$src" && test ! -d "$src"; then
189240a9a23Smbalmer      echo "$0: $src does not exist." >&2
190240a9a23Smbalmer      exit 1
191240a9a23Smbalmer    fi
192240a9a23Smbalmer
193240a9a23Smbalmer    if test -z "$dstarg"; then
194240a9a23Smbalmer      echo "$0: no destination specified." >&2
195240a9a23Smbalmer      exit 1
196240a9a23Smbalmer    fi
197240a9a23Smbalmer
198240a9a23Smbalmer    dst=$dstarg
199240a9a23Smbalmer    # Protect names starting with `-'.
200240a9a23Smbalmer    case $dst in
201240a9a23Smbalmer      -*) dst=./$dst ;;
202240a9a23Smbalmer    esac
203240a9a23Smbalmer
204240a9a23Smbalmer    # If destination is a directory, append the input filename; won't work
205240a9a23Smbalmer    # if double slashes aren't ignored.
206240a9a23Smbalmer    if test -d "$dst"; then
207240a9a23Smbalmer      if test -n "$no_target_directory"; then
208240a9a23Smbalmer	echo "$0: $dstarg: Is a directory" >&2
209240a9a23Smbalmer	exit 1
210240a9a23Smbalmer      fi
211240a9a23Smbalmer      dst=$dst/`basename "$src"`
212240a9a23Smbalmer    fi
213240a9a23Smbalmer  fi
214240a9a23Smbalmer
215240a9a23Smbalmer  # This sed command emulates the dirname command.
216240a9a23Smbalmer  dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'`
217240a9a23Smbalmer
218240a9a23Smbalmer  # Make sure that the destination directory exists.
219240a9a23Smbalmer
220240a9a23Smbalmer  # Skip lots of stat calls in the usual case.
221240a9a23Smbalmer  if test ! -d "$dstdir"; then
222240a9a23Smbalmer    defaultIFS='
223240a9a23Smbalmer	 '
224240a9a23Smbalmer    IFS="${IFS-$defaultIFS}"
225240a9a23Smbalmer
226240a9a23Smbalmer    oIFS=$IFS
227240a9a23Smbalmer    # Some sh's can't handle IFS=/ for some reason.
228240a9a23Smbalmer    IFS='%'
229240a9a23Smbalmer    set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
230240a9a23Smbalmer    shift
231240a9a23Smbalmer    IFS=$oIFS
232240a9a23Smbalmer
233240a9a23Smbalmer    pathcomp=
234240a9a23Smbalmer
235240a9a23Smbalmer    while test $# -ne 0 ; do
236240a9a23Smbalmer      pathcomp=$pathcomp$1
237240a9a23Smbalmer      shift
238240a9a23Smbalmer      if test ! -d "$pathcomp"; then
239240a9a23Smbalmer        $mkdirprog "$pathcomp"
240240a9a23Smbalmer	# mkdir can fail with a `File exist' error in case several
241240a9a23Smbalmer	# install-sh are creating the directory concurrently.  This
242240a9a23Smbalmer	# is OK.
243240a9a23Smbalmer	test -d "$pathcomp" || exit
244240a9a23Smbalmer      fi
245240a9a23Smbalmer      pathcomp=$pathcomp/
246240a9a23Smbalmer    done
247240a9a23Smbalmer  fi
248240a9a23Smbalmer
249240a9a23Smbalmer  if test -n "$dir_arg"; then
250240a9a23Smbalmer    $doit $mkdircmd "$dst" \
251240a9a23Smbalmer      && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
252240a9a23Smbalmer      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
253240a9a23Smbalmer      && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
254240a9a23Smbalmer      && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
255240a9a23Smbalmer
256240a9a23Smbalmer  else
257240a9a23Smbalmer    dstfile=`basename "$dst"`
258240a9a23Smbalmer
259240a9a23Smbalmer    # Make a couple of temp file names in the proper directory.
260240a9a23Smbalmer    dsttmp=$dstdir/_inst.$$_
261240a9a23Smbalmer    rmtmp=$dstdir/_rm.$$_
262240a9a23Smbalmer
263240a9a23Smbalmer    # Trap to clean up those temp files at exit.
264240a9a23Smbalmer    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
265240a9a23Smbalmer    trap '(exit $?); exit' 1 2 13 15
266240a9a23Smbalmer
267240a9a23Smbalmer    # Copy the file name to the temp name.
268240a9a23Smbalmer    $doit $cpprog "$src" "$dsttmp" &&
269240a9a23Smbalmer
270240a9a23Smbalmer    # and set any options; do chmod last to preserve setuid bits.
271240a9a23Smbalmer    #
272240a9a23Smbalmer    # If any of these fail, we abort the whole thing.  If we want to
273240a9a23Smbalmer    # ignore errors from any of these, just make sure not to ignore
274240a9a23Smbalmer    # errors from the above "$doit $cpprog $src $dsttmp" command.
275240a9a23Smbalmer    #
276240a9a23Smbalmer    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
277240a9a23Smbalmer      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
278240a9a23Smbalmer      && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
279240a9a23Smbalmer      && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
280240a9a23Smbalmer
281240a9a23Smbalmer    # Now rename the file to the real destination.
282240a9a23Smbalmer    { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
283240a9a23Smbalmer      || {
284240a9a23Smbalmer	   # The rename failed, perhaps because mv can't rename something else
285240a9a23Smbalmer	   # to itself, or perhaps because mv is so ancient that it does not
286240a9a23Smbalmer	   # support -f.
287240a9a23Smbalmer
288240a9a23Smbalmer	   # Now remove or move aside any old file at destination location.
289240a9a23Smbalmer	   # We try this two ways since rm can't unlink itself on some
290240a9a23Smbalmer	   # systems and the destination file might be busy for other
291240a9a23Smbalmer	   # reasons.  In this case, the final cleanup might fail but the new
292240a9a23Smbalmer	   # file should still install successfully.
293240a9a23Smbalmer	   {
294240a9a23Smbalmer	     if test -f "$dstdir/$dstfile"; then
295240a9a23Smbalmer	       $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
296240a9a23Smbalmer	       || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
297240a9a23Smbalmer	       || {
298240a9a23Smbalmer		 echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
299240a9a23Smbalmer		 (exit 1); exit 1
300240a9a23Smbalmer	       }
301240a9a23Smbalmer	     else
302240a9a23Smbalmer	       :
303240a9a23Smbalmer	     fi
304240a9a23Smbalmer	   } &&
305240a9a23Smbalmer
306240a9a23Smbalmer	   # Now rename the file to the real destination.
307240a9a23Smbalmer	   $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
308240a9a23Smbalmer	 }
309240a9a23Smbalmer    }
310240a9a23Smbalmer  fi || { (exit 1); exit 1; }
311240a9a23Smbalmerdone
312240a9a23Smbalmer
313240a9a23Smbalmer# The final little trick to "correctly" pass the exit status to the exit trap.
314240a9a23Smbalmer{
315240a9a23Smbalmer  (exit 0); exit 0
316240a9a23Smbalmer}
317240a9a23Smbalmer
318240a9a23Smbalmer# Local variables:
319240a9a23Smbalmer# eval: (add-hook 'write-file-hooks 'time-stamp)
320240a9a23Smbalmer# time-stamp-start: "scriptversion="
321240a9a23Smbalmer# time-stamp-format: "%:y-%02m-%02d.%02H"
322240a9a23Smbalmer# time-stamp-end: "$"
323240a9a23Smbalmer# End:
324