1251883Speter#!/bin/sh
2251883Speter# install - install a program, script, or datafile
3251883Speter
4251883Speterscriptversion=2005-05-14.22
5251883Speter
6251883Speter# This originates from X11R5 (mit/util/scripts/install.sh), which was
7251883Speter# later released in X11R6 (xc/config/util/install.sh) with the
8251883Speter# following copyright and license.
9251883Speter#
10251883Speter# Copyright (C) 1994 X Consortium
11251883Speter#
12251883Speter# Permission is hereby granted, free of charge, to any person obtaining a copy
13251883Speter# of this software and associated documentation files (the "Software"), to
14251883Speter# deal in the Software without restriction, including without limitation the
15251883Speter# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16251883Speter# sell copies of the Software, and to permit persons to whom the Software is
17251883Speter# furnished to do so, subject to the following conditions:
18251883Speter#
19251883Speter# The above copyright notice and this permission notice shall be included in
20251883Speter# all copies or substantial portions of the Software.
21251883Speter#
22251883Speter# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23251883Speter# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24251883Speter# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
25251883Speter# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26251883Speter# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
27251883Speter# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28251883Speter#
29251883Speter# Except as contained in this notice, the name of the X Consortium shall not
30251883Speter# be used in advertising or otherwise to promote the sale, use or other deal-
31251883Speter# ings in this Software without prior written authorization from the X Consor-
32251883Speter# tium.
33251883Speter#
34251883Speter#
35251883Speter# FSF changes to this file are in the public domain.
36251883Speter#
37251883Speter# Calling this script install-sh is preferred over install.sh, to prevent
38251883Speter# `make' implicit rules from creating a file called install from it
39251883Speter# when there is no Makefile.
40251883Speter#
41251883Speter# This script is compatible with the BSD install script, but was written
42251883Speter# from scratch.  It can only install one file at a time, a restriction
43251883Speter# shared with many OS's install programs.
44251883Speter
45251883Speter# set DOITPROG to echo to test this script
46251883Speter
47251883Speter# Don't use :- since 4.3BSD and earlier shells don't like it.
48251883Speterdoit="${DOITPROG-}"
49251883Speter
50251883Speter# put in absolute paths if you don't have them in your path; or use env. vars.
51251883Speter
52251883Spetermvprog="${MVPROG-mv}"
53251883Spetercpprog="${CPPROG-cp}"
54251883Speterchmodprog="${CHMODPROG-chmod}"
55251883Speterchownprog="${CHOWNPROG-chown}"
56251883Speterchgrpprog="${CHGRPPROG-chgrp}"
57251883Speterstripprog="${STRIPPROG-strip}"
58251883Speterrmprog="${RMPROG-rm}"
59251883Spetermkdirprog="${MKDIRPROG-mkdir}"
60251883Speter
61251883Speterchmodcmd="$chmodprog 0755"
62251883Speterchowncmd=
63251883Speterchgrpcmd=
64251883Speterstripcmd=
65251883Speterrmcmd="$rmprog -f"
66251883Spetermvcmd="$mvprog"
67251883Spetersrc=
68251883Speterdst=
69251883Speterdir_arg=
70251883Speterdstarg=
71251883Speterno_target_directory=
72251883Speter
73251883Speterusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
74251883Speter   or: $0 [OPTION]... SRCFILES... DIRECTORY
75251883Speter   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
76251883Speter   or: $0 [OPTION]... -d DIRECTORIES...
77251883Speter
78251883SpeterIn the 1st form, copy SRCFILE to DSTFILE.
79251883SpeterIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
80251883SpeterIn the 4th, create DIRECTORIES.
81251883Speter
82251883SpeterOptions:
83251883Speter-c         (ignored)
84251883Speter-d         create directories instead of installing files.
85251883Speter-g GROUP   $chgrpprog installed files to GROUP.
86251883Speter-m MODE    $chmodprog installed files to MODE.
87251883Speter-o USER    $chownprog installed files to USER.
88251883Speter-s         $stripprog installed files.
89251883Speter-t DIRECTORY  install into DIRECTORY.
90251883Speter-T         report an error if DSTFILE is a directory.
91251883Speter--help     display this help and exit.
92251883Speter--version  display version info and exit.
93251883Speter
94251883SpeterEnvironment variables override the default commands:
95251883Speter  CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
96251883Speter"
97251883Speter
98251883Speterwhile test -n "$1"; do
99251883Speter  case $1 in
100251883Speter    -c) shift
101251883Speter        continue;;
102251883Speter
103251883Speter    -d) dir_arg=true
104251883Speter        shift
105251883Speter        continue;;
106251883Speter
107251883Speter    -g) chgrpcmd="$chgrpprog $2"
108251883Speter        shift
109251883Speter        shift
110251883Speter        continue;;
111251883Speter
112251883Speter    --help) echo "$usage"; exit $?;;
113251883Speter
114251883Speter    -m) chmodcmd="$chmodprog $2"
115251883Speter        shift
116251883Speter        shift
117251883Speter        continue;;
118251883Speter
119251883Speter    -o) chowncmd="$chownprog $2"
120251883Speter        shift
121251883Speter        shift
122251883Speter        continue;;
123251883Speter
124251883Speter    -s) stripcmd=$stripprog
125251883Speter        shift
126251883Speter        continue;;
127251883Speter
128251883Speter    -t) dstarg=$2
129251883Speter	shift
130251883Speter	shift
131251883Speter	continue;;
132251883Speter
133251883Speter    -T) no_target_directory=true
134251883Speter	shift
135251883Speter	continue;;
136251883Speter
137251883Speter    --version) echo "$0 $scriptversion"; exit $?;;
138251883Speter
139251883Speter    *)  # When -d is used, all remaining arguments are directories to create.
140251883Speter	# When -t is used, the destination is already specified.
141251883Speter	test -n "$dir_arg$dstarg" && break
142251883Speter        # Otherwise, the last argument is the destination.  Remove it from $@.
143251883Speter	for arg
144251883Speter	do
145251883Speter          if test -n "$dstarg"; then
146251883Speter	    # $@ is not empty: it contains at least $arg.
147251883Speter	    set fnord "$@" "$dstarg"
148251883Speter	    shift # fnord
149251883Speter	  fi
150251883Speter	  shift # arg
151251883Speter	  dstarg=$arg
152251883Speter	done
153251883Speter	break;;
154251883Speter  esac
155251883Speterdone
156251883Speter
157251883Speterif test -z "$1"; then
158251883Speter  if test -z "$dir_arg"; then
159251883Speter    echo "$0: no input file specified." >&2
160251883Speter    exit 1
161251883Speter  fi
162251883Speter  # It's OK to call `install-sh -d' without argument.
163251883Speter  # This can happen when creating conditional directories.
164251883Speter  exit 0
165251883Speterfi
166251883Speter
167251883Speterfor src
168251883Speterdo
169251883Speter  # Protect names starting with `-'.
170251883Speter  case $src in
171251883Speter    -*) src=./$src ;;
172251883Speter  esac
173251883Speter
174251883Speter  if test -n "$dir_arg"; then
175251883Speter    dst=$src
176251883Speter    src=
177251883Speter
178251883Speter    if test -d "$dst"; then
179251883Speter      mkdircmd=:
180251883Speter      chmodcmd=
181251883Speter    else
182251883Speter      mkdircmd=$mkdirprog
183251883Speter    fi
184251883Speter  else
185251883Speter    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
186251883Speter    # might cause directories to be created, which would be especially bad
187251883Speter    # if $src (and thus $dsttmp) contains '*'.
188251883Speter    if test ! -f "$src" && test ! -d "$src"; then
189251883Speter      echo "$0: $src does not exist." >&2
190251883Speter      exit 1
191251883Speter    fi
192251883Speter
193251883Speter    if test -z "$dstarg"; then
194251883Speter      echo "$0: no destination specified." >&2
195251883Speter      exit 1
196251883Speter    fi
197251883Speter
198251883Speter    dst=$dstarg
199251883Speter    # Protect names starting with `-'.
200251883Speter    case $dst in
201251883Speter      -*) dst=./$dst ;;
202251883Speter    esac
203251883Speter
204251883Speter    # If destination is a directory, append the input filename; won't work
205251883Speter    # if double slashes aren't ignored.
206251883Speter    if test -d "$dst"; then
207251883Speter      if test -n "$no_target_directory"; then
208251883Speter	echo "$0: $dstarg: Is a directory" >&2
209251883Speter	exit 1
210251883Speter      fi
211251883Speter      dst=$dst/`basename "$src"`
212251883Speter    fi
213251883Speter  fi
214251883Speter
215251883Speter  # This sed command emulates the dirname command.
216251883Speter  dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'`
217251883Speter
218251883Speter  # Make sure that the destination directory exists.
219251883Speter
220251883Speter  # Skip lots of stat calls in the usual case.
221251883Speter  if test ! -d "$dstdir"; then
222251883Speter    defaultIFS='
223251883Speter	 '
224251883Speter    IFS="${IFS-$defaultIFS}"
225251883Speter
226251883Speter    oIFS=$IFS
227251883Speter    # Some sh's can't handle IFS=/ for some reason.
228251883Speter    IFS='%'
229251883Speter    set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
230251883Speter    shift
231251883Speter    IFS=$oIFS
232251883Speter
233251883Speter    pathcomp=
234251883Speter
235251883Speter    while test $# -ne 0 ; do
236251883Speter      pathcomp=$pathcomp$1
237251883Speter      shift
238251883Speter      if test ! -d "$pathcomp"; then
239251883Speter        $mkdirprog "$pathcomp"
240251883Speter	# mkdir can fail with a `File exist' error in case several
241251883Speter	# install-sh are creating the directory concurrently.  This
242251883Speter	# is OK.
243251883Speter	test -d "$pathcomp" || exit
244251883Speter      fi
245251883Speter      pathcomp=$pathcomp/
246251883Speter    done
247251883Speter  fi
248251883Speter
249251883Speter  if test -n "$dir_arg"; then
250251883Speter    $doit $mkdircmd "$dst" \
251251883Speter      && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
252251883Speter      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
253251883Speter      && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
254251883Speter      && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
255251883Speter
256251883Speter  else
257251883Speter    dstfile=`basename "$dst"`
258251883Speter
259251883Speter    # Make a couple of temp file names in the proper directory.
260251883Speter    dsttmp=$dstdir/_inst.$$_
261251883Speter    rmtmp=$dstdir/_rm.$$_
262251883Speter
263251883Speter    # Trap to clean up those temp files at exit.
264251883Speter    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
265251883Speter    trap '(exit $?); exit' 1 2 13 15
266251883Speter
267251883Speter    # Copy the file name to the temp name.
268251883Speter    $doit $cpprog "$src" "$dsttmp" &&
269251883Speter
270251883Speter    # and set any options; do chmod last to preserve setuid bits.
271251883Speter    #
272251883Speter    # If any of these fail, we abort the whole thing.  If we want to
273251883Speter    # ignore errors from any of these, just make sure not to ignore
274251883Speter    # errors from the above "$doit $cpprog $src $dsttmp" command.
275251883Speter    #
276251883Speter    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
277251883Speter      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
278251883Speter      && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
279251883Speter      && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
280251883Speter
281251883Speter    # Now rename the file to the real destination.
282251883Speter    { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
283251883Speter      || {
284251883Speter	   # The rename failed, perhaps because mv can't rename something else
285251883Speter	   # to itself, or perhaps because mv is so ancient that it does not
286251883Speter	   # support -f.
287251883Speter
288251883Speter	   # Now remove or move aside any old file at destination location.
289251883Speter	   # We try this two ways since rm can't unlink itself on some
290251883Speter	   # systems and the destination file might be busy for other
291251883Speter	   # reasons.  In this case, the final cleanup might fail but the new
292251883Speter	   # file should still install successfully.
293251883Speter	   {
294251883Speter	     if test -f "$dstdir/$dstfile"; then
295251883Speter	       $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
296251883Speter	       || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
297251883Speter	       || {
298251883Speter		 echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
299251883Speter		 (exit 1); exit 1
300251883Speter	       }
301251883Speter	     else
302251883Speter	       :
303251883Speter	     fi
304251883Speter	   } &&
305251883Speter
306251883Speter	   # Now rename the file to the real destination.
307251883Speter	   $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
308251883Speter	 }
309251883Speter    }
310251883Speter  fi || { (exit 1); exit 1; }
311251883Speterdone
312251883Speter
313251883Speter# The final little trick to "correctly" pass the exit status to the exit trap.
314251883Speter{
315251883Speter  (exit 0); exit 0
316251883Speter}
317251883Speter
318251883Speter# Local variables:
319251883Speter# eval: (add-hook 'write-file-hooks 'time-stamp)
320251883Speter# time-stamp-start: "scriptversion="
321251883Speter# time-stamp-format: "%:y-%02m-%02d.%02H"
322251883Speter# time-stamp-end: "$"
323251883Speter# End:
324