1130803Smarcel#!/bin/sh
2130803Smarcel# install - install a program, script, or datafile
3130803Smarcel
4130803Smarcelscriptversion=2004-02-15.20
5130803Smarcel
6130803Smarcel# This originates from X11R5 (mit/util/scripts/install.sh), which was
7130803Smarcel# later released in X11R6 (xc/config/util/install.sh) with the
8130803Smarcel# following copyright and license.
9130803Smarcel#
10130803Smarcel# Copyright (C) 1994 X Consortium
11130803Smarcel#
12130803Smarcel# Permission is hereby granted, free of charge, to any person obtaining a copy
13130803Smarcel# of this software and associated documentation files (the "Software"), to
14130803Smarcel# deal in the Software without restriction, including without limitation the
15130803Smarcel# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16130803Smarcel# sell copies of the Software, and to permit persons to whom the Software is
17130803Smarcel# furnished to do so, subject to the following conditions:
18130803Smarcel#
19130803Smarcel# The above copyright notice and this permission notice shall be included in
20130803Smarcel# all copies or substantial portions of the Software.
21130803Smarcel#
22130803Smarcel# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23130803Smarcel# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24130803Smarcel# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
25130803Smarcel# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26130803Smarcel# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
27130803Smarcel# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28130803Smarcel#
29130803Smarcel# Except as contained in this notice, the name of the X Consortium shall not
30130803Smarcel# be used in advertising or otherwise to promote the sale, use or other deal-
31130803Smarcel# ings in this Software without prior written authorization from the X Consor-
32130803Smarcel# tium.
33130803Smarcel#
34130803Smarcel#
35130803Smarcel# FSF changes to this file are in the public domain.
36130803Smarcel#
37130803Smarcel# Calling this script install-sh is preferred over install.sh, to prevent
38130803Smarcel# `make' implicit rules from creating a file called install from it
39130803Smarcel# when there is no Makefile.
40130803Smarcel#
41130803Smarcel# This script is compatible with the BSD install script, but was written
42130803Smarcel# from scratch.  It can only install one file at a time, a restriction
43130803Smarcel# shared with many OS's install programs.
44130803Smarcel
45130803Smarcel# set DOITPROG to echo to test this script
46130803Smarcel
47130803Smarcel# Don't use :- since 4.3BSD and earlier shells don't like it.
48130803Smarceldoit="${DOITPROG-}"
49130803Smarcel
50130803Smarcel# put in absolute paths if you don't have them in your path; or use env. vars.
51130803Smarcel
52130803Smarcelmvprog="${MVPROG-mv}"
53130803Smarcelcpprog="${CPPROG-cp}"
54130803Smarcelchmodprog="${CHMODPROG-chmod}"
55130803Smarcelchownprog="${CHOWNPROG-chown}"
56130803Smarcelchgrpprog="${CHGRPPROG-chgrp}"
57130803Smarcelstripprog="${STRIPPROG-strip}"
58130803Smarcelrmprog="${RMPROG-rm}"
59130803Smarcelmkdirprog="${MKDIRPROG-mkdir}"
60130803Smarcel
61130803Smarceltransformbasename=
62130803Smarceltransform_arg=
63130803Smarcelinstcmd="$mvprog"
64130803Smarcelchmodcmd="$chmodprog 0755"
65130803Smarcelchowncmd=
66130803Smarcelchgrpcmd=
67130803Smarcelstripcmd=
68130803Smarcelrmcmd="$rmprog -f"
69130803Smarcelmvcmd="$mvprog"
70130803Smarcelsrc=
71130803Smarceldst=
72130803Smarceldir_arg=
73130803Smarcel
74130803Smarcelusage="Usage: $0 [OPTION]... SRCFILE DSTFILE
75130803Smarcel   or: $0 [OPTION]... SRCFILES... DIRECTORY
76130803Smarcel   or: $0 -d DIRECTORIES...
77130803Smarcel
78130803SmarcelIn the first form, install SRCFILE to DSTFILE, removing SRCFILE by default.
79130803SmarcelIn the second, create the directory path DIR.
80130803Smarcel
81130803SmarcelOptions:
82130803Smarcel-b=TRANSFORMBASENAME
83130803Smarcel-c         copy source (using $cpprog) instead of moving (using $mvprog).
84130803Smarcel-d         create directories instead of installing files.
85130803Smarcel-g GROUP   $chgrp installed files to GROUP.
86130803Smarcel-m MODE    $chmod installed files to MODE.
87130803Smarcel-o USER    $chown installed files to USER.
88130803Smarcel-s         strip installed files (using $stripprog).
89130803Smarcel-t=TRANSFORM
90130803Smarcel--help     display this help and exit.
91130803Smarcel--version  display version info and exit.
92130803Smarcel
93130803SmarcelEnvironment variables override the default commands:
94130803Smarcel  CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
95130803Smarcel"
96130803Smarcel
97130803Smarcelwhile test -n "$1"; do
98130803Smarcel  case $1 in
99130803Smarcel    -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
100130803Smarcel        shift
101130803Smarcel        continue;;
102130803Smarcel
103130803Smarcel    -c) instcmd=$cpprog
104130803Smarcel        shift
105130803Smarcel        continue;;
106130803Smarcel
107130803Smarcel    -d) dir_arg=true
108130803Smarcel        shift
109130803Smarcel        continue;;
110130803Smarcel
111130803Smarcel    -g) chgrpcmd="$chgrpprog $2"
112130803Smarcel        shift
113130803Smarcel        shift
114130803Smarcel        continue;;
115130803Smarcel
116130803Smarcel    --help) echo "$usage"; exit 0;;
117130803Smarcel
118130803Smarcel    -m) chmodcmd="$chmodprog $2"
119130803Smarcel        shift
120130803Smarcel        shift
121130803Smarcel        continue;;
122130803Smarcel
123130803Smarcel    -o) chowncmd="$chownprog $2"
124130803Smarcel        shift
125130803Smarcel        shift
126130803Smarcel        continue;;
127130803Smarcel
128130803Smarcel    -s) stripcmd=$stripprog
129130803Smarcel        shift
130130803Smarcel        continue;;
131130803Smarcel
132130803Smarcel    -t=*) transformarg=`echo $1 | sed 's/-t=//'`
133130803Smarcel        shift
134130803Smarcel        continue;;
135130803Smarcel
136130803Smarcel    --version) echo "$0 $scriptversion"; exit 0;;
137130803Smarcel
138130803Smarcel    *)  # When -d is used, all remaining arguments are directories to create.
139130803Smarcel	test -n "$dir_arg" && break
140130803Smarcel        # Otherwise, the last argument is the destination.  Remove it from $@.
141130803Smarcel	for arg
142130803Smarcel	do
143130803Smarcel          if test -n "$dstarg"; then
144130803Smarcel	    # $@ is not empty: it contains at least $arg.
145130803Smarcel	    set fnord "$@" "$dstarg"
146130803Smarcel	    shift # fnord
147130803Smarcel	  fi
148130803Smarcel	  shift # arg
149130803Smarcel	  dstarg=$arg
150130803Smarcel	done
151130803Smarcel	break;;
152130803Smarcel  esac
153130803Smarceldone
154130803Smarcel
155130803Smarcelif test -z "$1"; then
156130803Smarcel  if test -z "$dir_arg"; then
157130803Smarcel    echo "$0: no input file specified." >&2
158130803Smarcel    exit 1
159130803Smarcel  fi
160130803Smarcel  # It's OK to call `install-sh -d' without argument.
161130803Smarcel  # This can happen when creating conditional directories.
162130803Smarcel  exit 0
163130803Smarcelfi
164130803Smarcel
165130803Smarcelfor src
166130803Smarceldo
167130803Smarcel  # Protect names starting with `-'.
168130803Smarcel  case $src in
169130803Smarcel    -*) src=./$src ;;
170130803Smarcel  esac
171130803Smarcel
172130803Smarcel  if test -n "$dir_arg"; then
173130803Smarcel    dst=$src
174130803Smarcel    src=
175130803Smarcel
176130803Smarcel    if test -d "$dst"; then
177130803Smarcel      instcmd=:
178130803Smarcel      chmodcmd=
179130803Smarcel    else
180130803Smarcel      instcmd=$mkdirprog
181130803Smarcel    fi
182130803Smarcel  else
183130803Smarcel    # Waiting for this to be detected by the "$instcmd $src $dsttmp" command
184130803Smarcel    # might cause directories to be created, which would be especially bad
185130803Smarcel    # if $src (and thus $dsttmp) contains '*'.
186130803Smarcel    if test ! -f "$src" && test ! -d "$src"; then
187130803Smarcel      echo "$0: $src does not exist." >&2
188130803Smarcel      exit 1
189130803Smarcel    fi
190130803Smarcel
191130803Smarcel    if test -z "$dstarg"; then
192130803Smarcel      echo "$0: no destination specified." >&2
193130803Smarcel      exit 1
194130803Smarcel    fi
195130803Smarcel
196130803Smarcel    dst=$dstarg
197130803Smarcel    # Protect names starting with `-'.
198130803Smarcel    case $dst in
199130803Smarcel      -*) dst=./$dst ;;
200130803Smarcel    esac
201130803Smarcel
202130803Smarcel    # If destination is a directory, append the input filename; won't work
203130803Smarcel    # if double slashes aren't ignored.
204130803Smarcel    if test -d "$dst"; then
205130803Smarcel      dst=$dst/`basename "$src"`
206130803Smarcel    fi
207130803Smarcel  fi
208130803Smarcel
209130803Smarcel  # This sed command emulates the dirname command.
210130803Smarcel  dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
211130803Smarcel
212130803Smarcel  # Make sure that the destination directory exists.
213130803Smarcel
214130803Smarcel  # Skip lots of stat calls in the usual case.
215130803Smarcel  if test ! -d "$dstdir"; then
216130803Smarcel    defaultIFS='
217130803Smarcel	 '
218130803Smarcel    IFS="${IFS-$defaultIFS}"
219130803Smarcel
220130803Smarcel    oIFS=$IFS
221130803Smarcel    # Some sh's can't handle IFS=/ for some reason.
222130803Smarcel    IFS='%'
223130803Smarcel    set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
224130803Smarcel    IFS=$oIFS
225130803Smarcel
226130803Smarcel    pathcomp=
227130803Smarcel
228130803Smarcel    while test $# -ne 0 ; do
229130803Smarcel      pathcomp=$pathcomp$1
230130803Smarcel      shift
231130803Smarcel      if test ! -d "$pathcomp"; then
232130803Smarcel        $mkdirprog "$pathcomp" || lasterr=$?
233130803Smarcel	# mkdir can fail with a `File exist' error in case several
234130803Smarcel	# install-sh are creating the directory concurrently.  This
235130803Smarcel	# is OK.
236130803Smarcel	test ! -d "$pathcomp" && { (exit ${lasterr-1}); exit; }
237130803Smarcel      fi
238130803Smarcel      pathcomp=$pathcomp/
239130803Smarcel    done
240130803Smarcel  fi
241130803Smarcel
242130803Smarcel  if test -n "$dir_arg"; then
243130803Smarcel    $doit $instcmd "$dst" \
244130803Smarcel      && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
245130803Smarcel      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
246130803Smarcel      && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
247130803Smarcel      && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
248130803Smarcel
249130803Smarcel  else
250130803Smarcel    # If we're going to rename the final executable, determine the name now.
251130803Smarcel    if test -z "$transformarg"; then
252130803Smarcel      dstfile=`basename "$dst"`
253130803Smarcel    else
254130803Smarcel      dstfile=`basename "$dst" $transformbasename \
255130803Smarcel               | sed $transformarg`$transformbasename
256130803Smarcel    fi
257130803Smarcel
258130803Smarcel    # don't allow the sed command to completely eliminate the filename.
259130803Smarcel    test -z "$dstfile" && dstfile=`basename "$dst"`
260130803Smarcel
261130803Smarcel    # Make a couple of temp file names in the proper directory.
262130803Smarcel    dsttmp=$dstdir/_inst.$$_
263130803Smarcel    rmtmp=$dstdir/_rm.$$_
264130803Smarcel
265130803Smarcel    # Trap to clean up those temp files at exit.
266130803Smarcel    trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
267130803Smarcel    trap '(exit $?); exit' 1 2 13 15
268130803Smarcel
269130803Smarcel    # Move or copy the file name to the temp name
270130803Smarcel    $doit $instcmd "$src" "$dsttmp" &&
271130803Smarcel
272130803Smarcel    # and set any options; do chmod last to preserve setuid bits.
273130803Smarcel    #
274130803Smarcel    # If any of these fail, we abort the whole thing.  If we want to
275130803Smarcel    # ignore errors from any of these, just make sure not to ignore
276130803Smarcel    # errors from the above "$doit $instcmd $src $dsttmp" command.
277130803Smarcel    #
278130803Smarcel    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
279130803Smarcel      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
280130803Smarcel      && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
281130803Smarcel      && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
282130803Smarcel
283130803Smarcel    # Now remove or move aside any old file at destination location.  We
284130803Smarcel    # try this two ways since rm can't unlink itself on some systems and
285130803Smarcel    # the destination file might be busy for other reasons.  In this case,
286130803Smarcel    # the final cleanup might fail but the new file should still install
287130803Smarcel    # successfully.
288130803Smarcel    {
289130803Smarcel      if test -f "$dstdir/$dstfile"; then
290130803Smarcel        $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
291130803Smarcel        || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
292130803Smarcel        || {
293130803Smarcel	  echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
294130803Smarcel	  (exit 1); exit
295130803Smarcel        }
296130803Smarcel      else
297130803Smarcel        :
298130803Smarcel      fi
299130803Smarcel    } &&
300130803Smarcel
301130803Smarcel    # Now rename the file to the real destination.
302130803Smarcel    $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
303130803Smarcel  fi || { (exit 1); exit; }
304130803Smarceldone
305130803Smarcel
306130803Smarcel# The final little trick to "correctly" pass the exit status to the exit trap.
307130803Smarcel{
308130803Smarcel  (exit 0); exit
309130803Smarcel}
310130803Smarcel
311130803Smarcel# Local variables:
312130803Smarcel# eval: (add-hook 'write-file-hooks 'time-stamp)
313130803Smarcel# time-stamp-start: "scriptversion="
314130803Smarcel# time-stamp-format: "%:y-%02m-%02d.%02H"
315130803Smarcel# time-stamp-end: "$"
316130803Smarcel# End:
317