159243Sobrien#!/bin/sh
259243Sobrien# install - install a program, script, or datafile
3145479Smp
4232633Smpscriptversion=2009-04-28.21; # UTC
5145479Smp
6145479Smp# This originates from X11R5 (mit/util/scripts/install.sh), which was
7145479Smp# later released in X11R6 (xc/config/util/install.sh) with the
8145479Smp# following copyright and license.
959243Sobrien#
10145479Smp# Copyright (C) 1994 X Consortium
1159243Sobrien#
12145479Smp# Permission is hereby granted, free of charge, to any person obtaining a copy
13145479Smp# of this software and associated documentation files (the "Software"), to
14145479Smp# deal in the Software without restriction, including without limitation the
15145479Smp# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16145479Smp# sell copies of the Software, and to permit persons to whom the Software is
17145479Smp# furnished to do so, subject to the following conditions:
1859243Sobrien#
19145479Smp# The above copyright notice and this permission notice shall be included in
20145479Smp# all copies or substantial portions of the Software.
21145479Smp#
22145479Smp# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23145479Smp# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24145479Smp# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
25145479Smp# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26145479Smp# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
27145479Smp# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28145479Smp#
29145479Smp# Except as contained in this notice, the name of the X Consortium shall not
30145479Smp# be used in advertising or otherwise to promote the sale, use or other deal-
31145479Smp# ings in this Software without prior written authorization from the X Consor-
32145479Smp# tium.
33145479Smp#
34145479Smp#
35145479Smp# FSF changes to this file are in the public domain.
36145479Smp#
3759243Sobrien# Calling this script install-sh is preferred over install.sh, to prevent
3859243Sobrien# `make' implicit rules from creating a file called install from it
3959243Sobrien# when there is no Makefile.
4059243Sobrien#
4159243Sobrien# This script is compatible with the BSD install script, but was written
42232633Smp# from scratch.
4359243Sobrien
44232633Smpnl='
45232633Smp'
46232633SmpIFS=" ""	$nl"
47232633Smp
4859243Sobrien# set DOITPROG to echo to test this script
4959243Sobrien
5059243Sobrien# Don't use :- since 4.3BSD and earlier shells don't like it.
51232633Smpdoit=${DOITPROG-}
52232633Smpif test -z "$doit"; then
53232633Smp  doit_exec=exec
54232633Smpelse
55232633Smp  doit_exec=$doit
56232633Smpfi
5759243Sobrien
58232633Smp# Put in absolute file names if you don't have them in your path;
59232633Smp# or use environment vars.
6059243Sobrien
61232633Smpchgrpprog=${CHGRPPROG-chgrp}
62232633Smpchmodprog=${CHMODPROG-chmod}
63232633Smpchownprog=${CHOWNPROG-chown}
64232633Smpcmpprog=${CMPPROG-cmp}
65232633Smpcpprog=${CPPROG-cp}
66232633Smpmkdirprog=${MKDIRPROG-mkdir}
67232633Smpmvprog=${MVPROG-mv}
68232633Smprmprog=${RMPROG-rm}
69232633Smpstripprog=${STRIPPROG-strip}
7059243Sobrien
71232633Smpposix_glob='?'
72232633Smpinitialize_posix_glob='
73232633Smp  test "$posix_glob" != "?" || {
74232633Smp    if (set -f) 2>/dev/null; then
75232633Smp      posix_glob=
76232633Smp    else
77232633Smp      posix_glob=:
78232633Smp    fi
79232633Smp  }
80232633Smp'
81232633Smp
82232633Smpposix_mkdir=
83232633Smp
84232633Smp# Desired mode of installed file.
85232633Smpmode=0755
86232633Smp
87232633Smpchgrpcmd=
88232633Smpchmodcmd=$chmodprog
89145479Smpchowncmd=
90232633Smpmvcmd=$mvprog
91232633Smprmcmd="$rmprog -f"
92145479Smpstripcmd=
93232633Smp
94145479Smpsrc=
95145479Smpdst=
96145479Smpdir_arg=
97232633Smpdst_arg=
98232633Smp
99232633Smpcopy_on_change=false
100145479Smpno_target_directory=
10159243Sobrien
102232633Smpusage="\
103232633SmpUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE
104145479Smp   or: $0 [OPTION]... SRCFILES... DIRECTORY
105145479Smp   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
106145479Smp   or: $0 [OPTION]... -d DIRECTORIES...
10759243Sobrien
108145479SmpIn the 1st form, copy SRCFILE to DSTFILE.
109145479SmpIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
110145479SmpIn the 4th, create DIRECTORIES.
11159243Sobrien
112145479SmpOptions:
113232633Smp     --help     display this help and exit.
114232633Smp     --version  display version info and exit.
11559243Sobrien
116232633Smp  -c            (ignored)
117232633Smp  -C            install only if different (preserve the last data modification time)
118232633Smp  -d            create directories instead of installing files.
119232633Smp  -g GROUP      $chgrpprog installed files to GROUP.
120232633Smp  -m MODE       $chmodprog installed files to MODE.
121232633Smp  -o USER       $chownprog installed files to USER.
122232633Smp  -s            $stripprog installed files.
123232633Smp  -t DIRECTORY  install into DIRECTORY.
124232633Smp  -T            report an error if DSTFILE is a directory.
125232633Smp
126145479SmpEnvironment variables override the default commands:
127232633Smp  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
128232633Smp  RMPROG STRIPPROG
129145479Smp"
13059243Sobrien
131232633Smpwhile test $# -ne 0; do
132145479Smp  case $1 in
133232633Smp    -c) ;;
13459243Sobrien
135232633Smp    -C) copy_on_change=true;;
13659243Sobrien
137232633Smp    -d) dir_arg=true;;
138232633Smp
139145479Smp    -g) chgrpcmd="$chgrpprog $2"
140232633Smp	shift;;
14159243Sobrien
142232633Smp    --help) echo "$usage"; exit $?;;
14359243Sobrien
144232633Smp    -m) mode=$2
145232633Smp	case $mode in
146232633Smp	  *' '* | *'	'* | *'
147232633Smp'*	  | *'*'* | *'?'* | *'['*)
148232633Smp	    echo "$0: invalid mode: $mode" >&2
149232633Smp	    exit 1;;
150232633Smp	esac
151232633Smp	shift;;
15259243Sobrien
153145479Smp    -o) chowncmd="$chownprog $2"
154232633Smp	shift;;
15559243Sobrien
156232633Smp    -s) stripcmd=$stripprog;;
15759243Sobrien
158232633Smp    -t) dst_arg=$2
159232633Smp	shift;;
16059243Sobrien
161232633Smp    -T) no_target_directory=true;;
16259243Sobrien
163232633Smp    --version) echo "$0 $scriptversion"; exit $?;;
16459243Sobrien
165232633Smp    --)	shift
166145479Smp	break;;
167232633Smp
168232633Smp    -*)	echo "$0: invalid option: $1" >&2
169232633Smp	exit 1;;
170232633Smp
171232633Smp    *)  break;;
172145479Smp  esac
173232633Smp  shift
174145479Smpdone
175145479Smp
176232633Smpif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
177232633Smp  # When -d is used, all remaining arguments are directories to create.
178232633Smp  # When -t is used, the destination is already specified.
179232633Smp  # Otherwise, the last argument is the destination.  Remove it from $@.
180232633Smp  for arg
181232633Smp  do
182232633Smp    if test -n "$dst_arg"; then
183232633Smp      # $@ is not empty: it contains at least $arg.
184232633Smp      set fnord "$@" "$dst_arg"
185232633Smp      shift # fnord
186232633Smp    fi
187232633Smp    shift # arg
188232633Smp    dst_arg=$arg
189232633Smp  done
190232633Smpfi
191232633Smp
192232633Smpif test $# -eq 0; then
193145479Smp  if test -z "$dir_arg"; then
194145479Smp    echo "$0: no input file specified." >&2
195145479Smp    exit 1
196145479Smp  fi
197145479Smp  # It's OK to call `install-sh -d' without argument.
198145479Smp  # This can happen when creating conditional directories.
199145479Smp  exit 0
20059243Sobrienfi
20159243Sobrien
202232633Smpif test -z "$dir_arg"; then
203232633Smp  trap '(exit $?); exit' 1 2 13 15
204232633Smp
205232633Smp  # Set umask so as not to create temps with too-generous modes.
206232633Smp  # However, 'strip' requires both read and write access to temps.
207232633Smp  case $mode in
208232633Smp    # Optimize common cases.
209232633Smp    *644) cp_umask=133;;
210232633Smp    *755) cp_umask=22;;
211232633Smp
212232633Smp    *[0-7])
213232633Smp      if test -z "$stripcmd"; then
214232633Smp	u_plus_rw=
215232633Smp      else
216232633Smp	u_plus_rw='% 200'
217232633Smp      fi
218232633Smp      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
219232633Smp    *)
220232633Smp      if test -z "$stripcmd"; then
221232633Smp	u_plus_rw=
222232633Smp      else
223232633Smp	u_plus_rw=,u+rw
224232633Smp      fi
225232633Smp      cp_umask=$mode$u_plus_rw;;
226232633Smp  esac
227232633Smpfi
228232633Smp
229145479Smpfor src
230145479Smpdo
231145479Smp  # Protect names starting with `-'.
232145479Smp  case $src in
233232633Smp    -*) src=./$src;;
234145479Smp  esac
23559243Sobrien
236145479Smp  if test -n "$dir_arg"; then
237145479Smp    dst=$src
238232633Smp    dstdir=$dst
239232633Smp    test -d "$dstdir"
240232633Smp    dstdir_status=$?
241232633Smp  else
24259243Sobrien
243145479Smp    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
244145479Smp    # might cause directories to be created, which would be especially bad
245145479Smp    # if $src (and thus $dsttmp) contains '*'.
246145479Smp    if test ! -f "$src" && test ! -d "$src"; then
247145479Smp      echo "$0: $src does not exist." >&2
248145479Smp      exit 1
249145479Smp    fi
25059243Sobrien
251232633Smp    if test -z "$dst_arg"; then
252145479Smp      echo "$0: no destination specified." >&2
253145479Smp      exit 1
254145479Smp    fi
25559243Sobrien
256232633Smp    dst=$dst_arg
257145479Smp    # Protect names starting with `-'.
258145479Smp    case $dst in
259232633Smp      -*) dst=./$dst;;
260145479Smp    esac
26159243Sobrien
262145479Smp    # If destination is a directory, append the input filename; won't work
263145479Smp    # if double slashes aren't ignored.
264145479Smp    if test -d "$dst"; then
265145479Smp      if test -n "$no_target_directory"; then
266232633Smp	echo "$0: $dst_arg: Is a directory" >&2
267145479Smp	exit 1
268145479Smp      fi
269232633Smp      dstdir=$dst
270232633Smp      dst=$dstdir/`basename "$src"`
271232633Smp      dstdir_status=0
272232633Smp    else
273232633Smp      # Prefer dirname, but fall back on a substitute if dirname fails.
274232633Smp      dstdir=`
275232633Smp	(dirname "$dst") 2>/dev/null ||
276232633Smp	expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
277232633Smp	     X"$dst" : 'X\(//\)[^/]' \| \
278232633Smp	     X"$dst" : 'X\(//\)$' \| \
279232633Smp	     X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
280232633Smp	echo X"$dst" |
281232633Smp	    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
282232633Smp		   s//\1/
283232633Smp		   q
284232633Smp		 }
285232633Smp		 /^X\(\/\/\)[^/].*/{
286232633Smp		   s//\1/
287232633Smp		   q
288232633Smp		 }
289232633Smp		 /^X\(\/\/\)$/{
290232633Smp		   s//\1/
291232633Smp		   q
292232633Smp		 }
293232633Smp		 /^X\(\/\).*/{
294232633Smp		   s//\1/
295232633Smp		   q
296232633Smp		 }
297232633Smp		 s/.*/./; q'
298232633Smp      `
299232633Smp
300232633Smp      test -d "$dstdir"
301232633Smp      dstdir_status=$?
302145479Smp    fi
303145479Smp  fi
30459243Sobrien
305232633Smp  obsolete_mkdir_used=false
30659243Sobrien
307232633Smp  if test $dstdir_status != 0; then
308232633Smp    case $posix_mkdir in
309232633Smp      '')
310232633Smp	# Create intermediate dirs using mode 755 as modified by the umask.
311232633Smp	# This is like FreeBSD 'install' as of 1997-10-28.
312232633Smp	umask=`umask`
313232633Smp	case $stripcmd.$umask in
314232633Smp	  # Optimize common cases.
315232633Smp	  *[2367][2367]) mkdir_umask=$umask;;
316232633Smp	  .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
31759243Sobrien
318232633Smp	  *[0-7])
319232633Smp	    mkdir_umask=`expr $umask + 22 \
320232633Smp	      - $umask % 100 % 40 + $umask % 20 \
321232633Smp	      - $umask % 10 % 4 + $umask % 2
322232633Smp	    `;;
323232633Smp	  *) mkdir_umask=$umask,go-w;;
324232633Smp	esac
32559243Sobrien
326232633Smp	# With -d, create the new directory with the user-specified mode.
327232633Smp	# Otherwise, rely on $mkdir_umask.
328232633Smp	if test -n "$dir_arg"; then
329232633Smp	  mkdir_mode=-m$mode
330232633Smp	else
331232633Smp	  mkdir_mode=
332232633Smp	fi
33359243Sobrien
334232633Smp	posix_mkdir=false
335232633Smp	case $umask in
336232633Smp	  *[123567][0-7][0-7])
337232633Smp	    # POSIX mkdir -p sets u+wx bits regardless of umask, which
338232633Smp	    # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
339232633Smp	    ;;
340232633Smp	  *)
341232633Smp	    tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
342232633Smp	    trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
34359243Sobrien
344232633Smp	    if (umask $mkdir_umask &&
345232633Smp		exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
346232633Smp	    then
347232633Smp	      if test -z "$dir_arg" || {
348232633Smp		   # Check for POSIX incompatibilities with -m.
349232633Smp		   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
350232633Smp		   # other-writeable bit of parent directory when it shouldn't.
351232633Smp		   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
352232633Smp		   ls_ld_tmpdir=`ls -ld "$tmpdir"`
353232633Smp		   case $ls_ld_tmpdir in
354232633Smp		     d????-?r-*) different_mode=700;;
355232633Smp		     d????-?--*) different_mode=755;;
356232633Smp		     *) false;;
357232633Smp		   esac &&
358232633Smp		   $mkdirprog -m$different_mode -p -- "$tmpdir" && {
359232633Smp		     ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
360232633Smp		     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
361232633Smp		   }
362232633Smp		 }
363232633Smp	      then posix_mkdir=:
364232633Smp	      fi
365232633Smp	      rmdir "$tmpdir/d" "$tmpdir"
366232633Smp	    else
367232633Smp	      # Remove any dirs left behind by ancient mkdir implementations.
368232633Smp	      rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
369232633Smp	    fi
370232633Smp	    trap '' 0;;
371232633Smp	esac;;
372232633Smp    esac
373232633Smp
374232633Smp    if
375232633Smp      $posix_mkdir && (
376232633Smp	umask $mkdir_umask &&
377232633Smp	$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
378232633Smp      )
379232633Smp    then :
380232633Smp    else
381232633Smp
382232633Smp      # The umask is ridiculous, or mkdir does not conform to POSIX,
383232633Smp      # or it failed possibly due to a race condition.  Create the
384232633Smp      # directory the slow way, step by step, checking for races as we go.
385232633Smp
386232633Smp      case $dstdir in
387232633Smp	/*) prefix='/';;
388232633Smp	-*) prefix='./';;
389232633Smp	*)  prefix='';;
390232633Smp      esac
391232633Smp
392232633Smp      eval "$initialize_posix_glob"
393232633Smp
394232633Smp      oIFS=$IFS
395232633Smp      IFS=/
396232633Smp      $posix_glob set -f
397232633Smp      set fnord $dstdir
398145479Smp      shift
399232633Smp      $posix_glob set +f
400232633Smp      IFS=$oIFS
401232633Smp
402232633Smp      prefixes=
403232633Smp
404232633Smp      for d
405232633Smp      do
406232633Smp	test -z "$d" && continue
407232633Smp
408232633Smp	prefix=$prefix$d
409232633Smp	if test -d "$prefix"; then
410232633Smp	  prefixes=
411232633Smp	else
412232633Smp	  if $posix_mkdir; then
413232633Smp	    (umask=$mkdir_umask &&
414232633Smp	     $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
415232633Smp	    # Don't fail if two instances are running concurrently.
416232633Smp	    test -d "$prefix" || exit 1
417232633Smp	  else
418232633Smp	    case $prefix in
419232633Smp	      *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
420232633Smp	      *) qprefix=$prefix;;
421232633Smp	    esac
422232633Smp	    prefixes="$prefixes '$qprefix'"
423232633Smp	  fi
424232633Smp	fi
425232633Smp	prefix=$prefix/
426232633Smp      done
427232633Smp
428232633Smp      if test -n "$prefixes"; then
429232633Smp	# Don't fail if two instances are running concurrently.
430232633Smp	(umask $mkdir_umask &&
431232633Smp	 eval "\$doit_exec \$mkdirprog $prefixes") ||
432232633Smp	  test -d "$dstdir" || exit 1
433232633Smp	obsolete_mkdir_used=true
434145479Smp      fi
435232633Smp    fi
436145479Smp  fi
43759243Sobrien
438145479Smp  if test -n "$dir_arg"; then
439232633Smp    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
440232633Smp    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
441232633Smp    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
442232633Smp      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
443145479Smp  else
44459243Sobrien
445145479Smp    # Make a couple of temp file names in the proper directory.
446145479Smp    dsttmp=$dstdir/_inst.$$_
447145479Smp    rmtmp=$dstdir/_rm.$$_
44859243Sobrien
449145479Smp    # Trap to clean up those temp files at exit.
450145479Smp    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
45159243Sobrien
452145479Smp    # Copy the file name to the temp name.
453232633Smp    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
45459243Sobrien
455145479Smp    # and set any options; do chmod last to preserve setuid bits.
456145479Smp    #
457145479Smp    # If any of these fail, we abort the whole thing.  If we want to
458145479Smp    # ignore errors from any of these, just make sure not to ignore
459145479Smp    # errors from the above "$doit $cpprog $src $dsttmp" command.
460145479Smp    #
461232633Smp    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
462232633Smp    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
463232633Smp    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
464232633Smp    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
46559243Sobrien
466232633Smp    # If -C, don't bother to copy if it wouldn't change the file.
467232633Smp    if $copy_on_change &&
468232633Smp       old=`LC_ALL=C ls -dlL "$dst"	2>/dev/null` &&
469232633Smp       new=`LC_ALL=C ls -dlL "$dsttmp"	2>/dev/null` &&
47059243Sobrien
471232633Smp       eval "$initialize_posix_glob" &&
472232633Smp       $posix_glob set -f &&
473232633Smp       set X $old && old=:$2:$4:$5:$6 &&
474232633Smp       set X $new && new=:$2:$4:$5:$6 &&
475232633Smp       $posix_glob set +f &&
47659243Sobrien
477232633Smp       test "$old" = "$new" &&
478232633Smp       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
479232633Smp    then
480232633Smp      rm -f "$dsttmp"
481232633Smp    else
482232633Smp      # Rename the file to the real destination.
483232633Smp      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
484232633Smp
485232633Smp      # The rename failed, perhaps because mv can't rename something else
486232633Smp      # to itself, or perhaps because mv is so ancient that it does not
487232633Smp      # support -f.
488232633Smp      {
489232633Smp	# Now remove or move aside any old file at destination location.
490232633Smp	# We try this two ways since rm can't unlink itself on some
491232633Smp	# systems and the destination file might be busy for other
492232633Smp	# reasons.  In this case, the final cleanup might fail but the new
493232633Smp	# file should still install successfully.
494232633Smp	{
495232633Smp	  test ! -f "$dst" ||
496232633Smp	  $doit $rmcmd -f "$dst" 2>/dev/null ||
497232633Smp	  { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
498232633Smp	    { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
499232633Smp	  } ||
500232633Smp	  { echo "$0: cannot unlink or rename $dst" >&2
501232633Smp	    (exit 1); exit 1
502232633Smp	  }
503232633Smp	} &&
504232633Smp
505232633Smp	# Now rename the file to the real destination.
506232633Smp	$doit $mvcmd "$dsttmp" "$dst"
507232633Smp      }
508232633Smp    fi || exit 1
509232633Smp
510232633Smp    trap '' 0
511232633Smp  fi
512145479Smpdone
51359243Sobrien
514145479Smp# Local variables:
515145479Smp# eval: (add-hook 'write-file-hooks 'time-stamp)
516145479Smp# time-stamp-start: "scriptversion="
517145479Smp# time-stamp-format: "%:y-%02m-%02d.%02H"
518232633Smp# time-stamp-time-zone: "UTC"
519232633Smp# time-stamp-end: "; # UTC"
520145479Smp# End:
521