UNIXworkcode

  1  #!/bin/sh
  2  # install - install a program, script, or datafile
  3  
  4  scriptversion=2013-12-25.23; # UTC
  5  
  6  # This originates from X11R5 (mit/util/scripts/install.sh), which was
  7  # later released in X11R6 (xc/config/util/install.sh) with the
  8  # following copyright and license.
  9  #
 10  # Copyright (C) 1994 X Consortium
 11  #
 12  # Permission is hereby granted, free of charge, to any person obtaining a copy
 13  # of this software and associated documentation files (the "Software"), to
 14  # deal in the Software without restriction, including without limitation the
 15  # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 16  # sell copies of the Software, and to permit persons to whom the Software is
 17  # furnished to do so, subject to the following conditions:
 18  #
 19  # The above copyright notice and this permission notice shall be included in
 20  # all copies or substantial portions of the Software.
 21  #
 22  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 23  # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 24  # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 25  # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 26  # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
 27  # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 28  #
 29  # Except as contained in this notice, the name of the X Consortium shall not
 30  # be used in advertising or otherwise to promote the sale, use or other deal-
 31  # ings in this Software without prior written authorization from the X Consor-
 32  # tium.
 33  #
 34  #
 35  # FSF changes to this file are in the public domain.
 36  #
 37  # Calling this script install-sh is preferred over install.sh, to prevent
 38  # 'make' implicit rules from creating a file called install from it
 39  # when there is no Makefile.
 40  #
 41  # This script is compatible with the BSD install script, but was written
 42  # from scratch.
 43  
 44  tab='	'
 45  nl='
 46  '
 47  IFS=" $tab$nl"
 48  
 49  # Set DOITPROG to "echo" to test this script.
 50  
 51  doit=${DOITPROG-}
 52  doit_exec=${doit:-exec}
 53  
 54  # Put in absolute file names if you don't have them in your path;
 55  # or use environment vars.
 56  
 57  chgrpprog=${CHGRPPROG-chgrp}
 58  chmodprog=${CHMODPROG-chmod}
 59  chownprog=${CHOWNPROG-chown}
 60  cmpprog=${CMPPROG-cmp}
 61  cpprog=${CPPROG-cp}
 62  mkdirprog=${MKDIRPROG-mkdir}
 63  mvprog=${MVPROG-mv}
 64  rmprog=${RMPROG-rm}
 65  stripprog=${STRIPPROG-strip}
 66  
 67  posix_mkdir=
 68  
 69  # Desired mode of installed file.
 70  mode=0755
 71  
 72  chgrpcmd=
 73  chmodcmd=$chmodprog
 74  chowncmd=
 75  mvcmd=$mvprog
 76  rmcmd="$rmprog -f"
 77  stripcmd=
 78  
 79  src=
 80  dst=
 81  dir_arg=
 82  dst_arg=
 83  
 84  copy_on_change=false
 85  is_target_a_directory=possibly
 86  
 87  usage="\
 88  Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
 89     or: $0 [OPTION]... SRCFILES... DIRECTORY
 90     or: $0 [OPTION]... -t DIRECTORY SRCFILES...
 91     or: $0 [OPTION]... -d DIRECTORIES...
 92  
 93  In the 1st form, copy SRCFILE to DSTFILE.
 94  In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
 95  In the 4th, create DIRECTORIES.
 96  
 97  Options:
 98       --help     display this help and exit.
 99       --version  display version info and exit.
100  
101    -c            (ignored)
102    -C            install only if different (preserve the last data modification time)
103    -d            create directories instead of installing files.
104    -g GROUP      $chgrpprog installed files to GROUP.
105    -m MODE       $chmodprog installed files to MODE.
106    -o USER       $chownprog installed files to USER.
107    -s            $stripprog installed files.
108    -t DIRECTORY  install into DIRECTORY.
109    -T            report an error if DSTFILE is a directory.
110  
111  Environment variables override the default commands:
112    CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
113    RMPROG STRIPPROG
114  "
115  
116  while test $# -ne 0; do
117    case $1 in
118      -c) ;;
119  
120      -C) copy_on_change=true;;
121  
122      -d) dir_arg=true;;
123  
124      -g) chgrpcmd="$chgrpprog $2"
125          shift;;
126  
127      --help) echo "$usage"; exit $?;;
128  
129      -m) mode=$2
130          case $mode in
131            *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
132              echo "$0: invalid mode: $mode" >&2
133              exit 1;;
134          esac
135          shift;;
136  
137      -o) chowncmd="$chownprog $2"
138          shift;;
139  
140      -s) stripcmd=$stripprog;;
141  
142      -t)
143          is_target_a_directory=always
144          dst_arg=$2
145          # Protect names problematic for 'test' and other utilities.
146          case $dst_arg in
147            -* | [=\(\)!]) dst_arg=./$dst_arg;;
148          esac
149          shift;;
150  
151      -T) is_target_a_directory=never;;
152  
153      --version) echo "$0 $scriptversion"; exit $?;;
154  
155      --) shift
156          break;;
157  
158      -*) echo "$0: invalid option: $1" >&2
159          exit 1;;
160  
161      *)  break;;
162    esac
163    shift
164  done
165  
166  # We allow the use of options -d and -T together, by making -d
167  # take the precedence; this is for compatibility with GNU install.
168  
169  if test -n "$dir_arg"; then
170    if test -n "$dst_arg"; then
171      echo "$0: target directory not allowed when installing a directory." >&2
172      exit 1
173    fi
174  fi
175  
176  if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
177    # When -d is used, all remaining arguments are directories to create.
178    # When -t is used, the destination is already specified.
179    # Otherwise, the last argument is the destination.  Remove it from $@.
180    for arg
181    do
182      if test -n "$dst_arg"; then
183        # $@ is not empty: it contains at least $arg.
184        set fnord "$@" "$dst_arg"
185        shift # fnord
186      fi
187      shift # arg
188      dst_arg=$arg
189      # Protect names problematic for 'test' and other utilities.
190      case $dst_arg in
191        -* | [=\(\)!]) dst_arg=./$dst_arg;;
192      esac
193    done
194  fi
195  
196  if test $# -eq 0; then
197    if test -z "$dir_arg"; then
198      echo "$0: no input file specified." >&2
199      exit 1
200    fi
201    # It's OK to call 'install-sh -d' without argument.
202    # This can happen when creating conditional directories.
203    exit 0
204  fi
205  
206  if test -z "$dir_arg"; then
207    if test $# -gt 1 || test "$is_target_a_directory" = always; then
208      if test ! -d "$dst_arg"; then
209        echo "$0: $dst_arg: Is not a directory." >&2
210        exit 1
211      fi
212    fi
213  fi
214  
215  if test -z "$dir_arg"; then
216    do_exit='(exit $ret); exit $ret'
217    trap "ret=129; $do_exit" 1
218    trap "ret=130; $do_exit" 2
219    trap "ret=141; $do_exit" 13
220    trap "ret=143; $do_exit" 15
221  
222    # Set umask so as not to create temps with too-generous modes.
223    # However, 'strip' requires both read and write access to temps.
224    case $mode in
225      # Optimize common cases.
226      *644) cp_umask=133;;
227      *755) cp_umask=22;;
228  
229      *[0-7])
230        if test -z "$stripcmd"; then
231          u_plus_rw=
232        else
233          u_plus_rw='% 200'
234        fi
235        cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
236      *)
237        if test -z "$stripcmd"; then
238          u_plus_rw=
239        else
240          u_plus_rw=,u+rw
241        fi
242        cp_umask=$mode$u_plus_rw;;
243    esac
244  fi
245  
246  for src
247  do
248    # Protect names problematic for 'test' and other utilities.
249    case $src in
250      -* | [=\(\)!]) src=./$src;;
251    esac
252  
253    if test -n "$dir_arg"; then
254      dst=$src
255      dstdir=$dst
256      test -d "$dstdir"
257      dstdir_status=$?
258    else
259  
260      # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
261      # might cause directories to be created, which would be especially bad
262      # if $src (and thus $dsttmp) contains '*'.
263      if test ! -f "$src" && test ! -d "$src"; then
264        echo "$0: $src does not exist." >&2
265        exit 1
266      fi
267  
268      if test -z "$dst_arg"; then
269        echo "$0: no destination specified." >&2
270        exit 1
271      fi
272      dst=$dst_arg
273  
274      # If destination is a directory, append the input filename; won't work
275      # if double slashes aren't ignored.
276      if test -d "$dst"; then
277        if test "$is_target_a_directory" = never; then
278          echo "$0: $dst_arg: Is a directory" >&2
279          exit 1
280        fi
281        dstdir=$dst
282        dst=$dstdir/`basename "$src"`
283        dstdir_status=0
284      else
285        dstdir=`dirname "$dst"`
286        test -d "$dstdir"
287        dstdir_status=$?
288      fi
289    fi
290  
291    obsolete_mkdir_used=false
292  
293    if test $dstdir_status != 0; then
294      case $posix_mkdir in
295        '')
296          # Create intermediate dirs using mode 755 as modified by the umask.
297          # This is like FreeBSD 'install' as of 1997-10-28.
298          umask=`umask`
299          case $stripcmd.$umask in
300            # Optimize common cases.
301            *[2367][2367]) mkdir_umask=$umask;;
302            .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
303  
304            *[0-7])
305              mkdir_umask=`expr $umask + 22 \
306                - $umask % 100 % 40 + $umask % 20 \
307                - $umask % 10 % 4 + $umask % 2
308              `;;
309            *) mkdir_umask=$umask,go-w;;
310          esac
311  
312          # With -d, create the new directory with the user-specified mode.
313          # Otherwise, rely on $mkdir_umask.
314          if test -n "$dir_arg"; then
315            mkdir_mode=-m$mode
316          else
317            mkdir_mode=
318          fi
319  
320          posix_mkdir=false
321          case $umask in
322            *[123567][0-7][0-7])
323              # POSIX mkdir -p sets u+wx bits regardless of umask, which
324              # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
325              ;;
326            *)
327              tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
328              trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
329  
330              if (umask $mkdir_umask &&
331                  exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
332              then
333                if test -z "$dir_arg" || {
334                     # Check for POSIX incompatibilities with -m.
335                     # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
336                     # other-writable bit of parent directory when it shouldn't.
337                     # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
338                     ls_ld_tmpdir=`ls -ld "$tmpdir"`
339                     case $ls_ld_tmpdir in
340                       d????-?r-*) different_mode=700;;
341                       d????-?--*) different_mode=755;;
342                       *) false;;
343                     esac &&
344                     $mkdirprog -m$different_mode -p -- "$tmpdir" && {
345                       ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
346                       test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
347                     }
348                   }
349                then posix_mkdir=:
350                fi
351                rmdir "$tmpdir/d" "$tmpdir"
352              else
353                # Remove any dirs left behind by ancient mkdir implementations.
354                rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
355              fi
356              trap '' 0;;
357          esac;;
358      esac
359  
360      if
361        $posix_mkdir && (
362          umask $mkdir_umask &&
363          $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
364        )
365      then :
366      else
367  
368        # The umask is ridiculous, or mkdir does not conform to POSIX,
369        # or it failed possibly due to a race condition.  Create the
370        # directory the slow way, step by step, checking for races as we go.
371  
372        case $dstdir in
373          /*) prefix='/';;
374          [-=\(\)!]*) prefix='./';;
375          *)  prefix='';;
376        esac
377  
378        oIFS=$IFS
379        IFS=/
380        set -f
381        set fnord $dstdir
382        shift
383        set +f
384        IFS=$oIFS
385  
386        prefixes=
387  
388        for d
389        do
390          test X"$d" = X && continue
391  
392          prefix=$prefix$d
393          if test -d "$prefix"; then
394            prefixes=
395          else
396            if $posix_mkdir; then
397              (umask=$mkdir_umask &&
398               $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
399              # Don't fail if two instances are running concurrently.
400              test -d "$prefix" || exit 1
401            else
402              case $prefix in
403                *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
404                *) qprefix=$prefix;;
405              esac
406              prefixes="$prefixes '$qprefix'"
407            fi
408          fi
409          prefix=$prefix/
410        done
411  
412        if test -n "$prefixes"; then
413          # Don't fail if two instances are running concurrently.
414          (umask $mkdir_umask &&
415           eval "\$doit_exec \$mkdirprog $prefixes") ||
416            test -d "$dstdir" || exit 1
417          obsolete_mkdir_used=true
418        fi
419      fi
420    fi
421  
422    if test -n "$dir_arg"; then
423      { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
424      { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
425      { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
426        test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
427    else
428  
429      # Make a couple of temp file names in the proper directory.
430      dsttmp=$dstdir/_inst.$$_
431      rmtmp=$dstdir/_rm.$$_
432  
433      # Trap to clean up those temp files at exit.
434      trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
435  
436      # Copy the file name to the temp name.
437      (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
438  
439      # and set any options; do chmod last to preserve setuid bits.
440      #
441      # If any of these fail, we abort the whole thing.  If we want to
442      # ignore errors from any of these, just make sure not to ignore
443      # errors from the above "$doit $cpprog $src $dsttmp" command.
444      #
445      { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
446      { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
447      { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
448      { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
449  
450      # If -C, don't bother to copy if it wouldn't change the file.
451      if $copy_on_change &&
452         old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
453         new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
454         set -f &&
455         set X $old && old=:$2:$4:$5:$6 &&
456         set X $new && new=:$2:$4:$5:$6 &&
457         set +f &&
458         test "$old" = "$new" &&
459         $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
460      then
461        rm -f "$dsttmp"
462      else
463        # Rename the file to the real destination.
464        $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
465  
466        # The rename failed, perhaps because mv can't rename something else
467        # to itself, or perhaps because mv is so ancient that it does not
468        # support -f.
469        {
470          # Now remove or move aside any old file at destination location.
471          # We try this two ways since rm can't unlink itself on some
472          # systems and the destination file might be busy for other
473          # reasons.  In this case, the final cleanup might fail but the new
474          # file should still install successfully.
475          {
476            test ! -f "$dst" ||
477            $doit $rmcmd -f "$dst" 2>/dev/null ||
478            { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
479              { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
480            } ||
481            { echo "$0: cannot unlink or rename $dst" >&2
482              (exit 1); exit 1
483            }
484          } &&
485  
486          # Now rename the file to the real destination.
487          $doit $mvcmd "$dsttmp" "$dst"
488        }
489      fi || exit 1
490  
491      trap '' 0
492    fi
493  done
494  
495  # Local variables:
496  # eval: (add-hook 'write-file-hooks 'time-stamp)
497  # time-stamp-start: "scriptversion="
498  # time-stamp-format: "%:y-%02m-%02d.%02H"
499  # time-stamp-time-zone: "UTC"
500  # time-stamp-end: "; # UTC"
501  # End: