annotate install-sh @ 0:d39e1d0d75b6

initial add
author paulo@hit-nxdomain.opendns.com
date Sat, 20 Feb 2010 21:18:28 -0800
parents
children
rev   line source
paulo@0 1 #!/bin/sh
paulo@0 2 #
paulo@0 3 # install - install a program, script, or datafile
paulo@0 4 #
paulo@0 5 # This originates from X11R5 (mit/util/scripts/install.sh), which was
paulo@0 6 # later released in X11R6 (xc/config/util/install.sh) with the
paulo@0 7 # following copyright and license.
paulo@0 8 #
paulo@0 9 # Copyright (C) 1994 X Consortium
paulo@0 10 #
paulo@0 11 # Permission is hereby granted, free of charge, to any person obtaining a copy
paulo@0 12 # of this software and associated documentation files (the "Software"), to
paulo@0 13 # deal in the Software without restriction, including without limitation the
paulo@0 14 # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
paulo@0 15 # sell copies of the Software, and to permit persons to whom the Software is
paulo@0 16 # furnished to do so, subject to the following conditions:
paulo@0 17 #
paulo@0 18 # The above copyright notice and this permission notice shall be included in
paulo@0 19 # all copies or substantial portions of the Software.
paulo@0 20 #
paulo@0 21 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
paulo@0 22 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
paulo@0 23 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
paulo@0 24 # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
paulo@0 25 # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
paulo@0 26 # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
paulo@0 27 #
paulo@0 28 # Except as contained in this notice, the name of the X Consortium shall not
paulo@0 29 # be used in advertising or otherwise to promote the sale, use or other deal-
paulo@0 30 # ings in this Software without prior written authorization from the X Consor-
paulo@0 31 # tium.
paulo@0 32 #
paulo@0 33 #
paulo@0 34 # FSF changes to this file are in the public domain.
paulo@0 35 #
paulo@0 36 # Calling this script install-sh is preferred over install.sh, to prevent
paulo@0 37 # `make' implicit rules from creating a file called install from it
paulo@0 38 # when there is no Makefile.
paulo@0 39 #
paulo@0 40 # This script is compatible with the BSD install script, but was written
paulo@0 41 # from scratch. It can only install one file at a time, a restriction
paulo@0 42 # shared with many OS's install programs.
paulo@0 43
paulo@0 44
paulo@0 45 # set DOITPROG to echo to test this script
paulo@0 46
paulo@0 47 # Don't use :- since 4.3BSD and earlier shells don't like it.
paulo@0 48 doit="${DOITPROG-}"
paulo@0 49
paulo@0 50
paulo@0 51 # put in absolute paths if you don't have them in your path; or use env. vars.
paulo@0 52
paulo@0 53 mvprog="${MVPROG-mv}"
paulo@0 54 cpprog="${CPPROG-cp}"
paulo@0 55 chmodprog="${CHMODPROG-chmod}"
paulo@0 56 chownprog="${CHOWNPROG-chown}"
paulo@0 57 chgrpprog="${CHGRPPROG-chgrp}"
paulo@0 58 stripprog="${STRIPPROG-strip}"
paulo@0 59 rmprog="${RMPROG-rm}"
paulo@0 60 mkdirprog="${MKDIRPROG-mkdir}"
paulo@0 61
paulo@0 62 transformbasename=""
paulo@0 63 transform_arg=""
paulo@0 64 instcmd="$mvprog"
paulo@0 65 chmodcmd="$chmodprog 0755"
paulo@0 66 chowncmd=""
paulo@0 67 chgrpcmd=""
paulo@0 68 stripcmd=""
paulo@0 69 rmcmd="$rmprog -f"
paulo@0 70 mvcmd="$mvprog"
paulo@0 71 src=""
paulo@0 72 dst=""
paulo@0 73 dir_arg=""
paulo@0 74
paulo@0 75 while [ x"$1" != x ]; do
paulo@0 76 case $1 in
paulo@0 77 -c) instcmd=$cpprog
paulo@0 78 shift
paulo@0 79 continue;;
paulo@0 80
paulo@0 81 -d) dir_arg=true
paulo@0 82 shift
paulo@0 83 continue;;
paulo@0 84
paulo@0 85 -m) chmodcmd="$chmodprog $2"
paulo@0 86 shift
paulo@0 87 shift
paulo@0 88 continue;;
paulo@0 89
paulo@0 90 -o) chowncmd="$chownprog $2"
paulo@0 91 shift
paulo@0 92 shift
paulo@0 93 continue;;
paulo@0 94
paulo@0 95 -g) chgrpcmd="$chgrpprog $2"
paulo@0 96 shift
paulo@0 97 shift
paulo@0 98 continue;;
paulo@0 99
paulo@0 100 -s) stripcmd=$stripprog
paulo@0 101 shift
paulo@0 102 continue;;
paulo@0 103
paulo@0 104 -t=*) transformarg=`echo $1 | sed 's/-t=//'`
paulo@0 105 shift
paulo@0 106 continue;;
paulo@0 107
paulo@0 108 -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
paulo@0 109 shift
paulo@0 110 continue;;
paulo@0 111
paulo@0 112 *) if [ x"$src" = x ]
paulo@0 113 then
paulo@0 114 src=$1
paulo@0 115 else
paulo@0 116 # this colon is to work around a 386BSD /bin/sh bug
paulo@0 117 :
paulo@0 118 dst=$1
paulo@0 119 fi
paulo@0 120 shift
paulo@0 121 continue;;
paulo@0 122 esac
paulo@0 123 done
paulo@0 124
paulo@0 125 if [ x"$src" = x ]
paulo@0 126 then
paulo@0 127 echo "$0: no input file specified" >&2
paulo@0 128 exit 1
paulo@0 129 else
paulo@0 130 :
paulo@0 131 fi
paulo@0 132
paulo@0 133 if [ x"$dir_arg" != x ]; then
paulo@0 134 dst=$src
paulo@0 135 src=""
paulo@0 136
paulo@0 137 if [ -d "$dst" ]; then
paulo@0 138 instcmd=:
paulo@0 139 chmodcmd=""
paulo@0 140 else
paulo@0 141 instcmd=$mkdirprog
paulo@0 142 fi
paulo@0 143 else
paulo@0 144
paulo@0 145 # Waiting for this to be detected by the "$instcmd $src $dsttmp" command
paulo@0 146 # might cause directories to be created, which would be especially bad
paulo@0 147 # if $src (and thus $dsttmp) contains '*'.
paulo@0 148
paulo@0 149 if [ -f "$src" ] || [ -d "$src" ]
paulo@0 150 then
paulo@0 151 :
paulo@0 152 else
paulo@0 153 echo "$0: $src does not exist" >&2
paulo@0 154 exit 1
paulo@0 155 fi
paulo@0 156
paulo@0 157 if [ x"$dst" = x ]
paulo@0 158 then
paulo@0 159 echo "$0: no destination specified" >&2
paulo@0 160 exit 1
paulo@0 161 else
paulo@0 162 :
paulo@0 163 fi
paulo@0 164
paulo@0 165 # If destination is a directory, append the input filename; if your system
paulo@0 166 # does not like double slashes in filenames, you may need to add some logic
paulo@0 167
paulo@0 168 if [ -d "$dst" ]
paulo@0 169 then
paulo@0 170 dst=$dst/`basename "$src"`
paulo@0 171 else
paulo@0 172 :
paulo@0 173 fi
paulo@0 174 fi
paulo@0 175
paulo@0 176 ## this sed command emulates the dirname command
paulo@0 177 dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
paulo@0 178
paulo@0 179 # Make sure that the destination directory exists.
paulo@0 180 # this part is taken from Noah Friedman's mkinstalldirs script
paulo@0 181
paulo@0 182 # Skip lots of stat calls in the usual case.
paulo@0 183 if [ ! -d "$dstdir" ]; then
paulo@0 184 defaultIFS='
paulo@0 185 '
paulo@0 186 IFS="${IFS-$defaultIFS}"
paulo@0 187
paulo@0 188 oIFS=$IFS
paulo@0 189 # Some sh's can't handle IFS=/ for some reason.
paulo@0 190 IFS='%'
paulo@0 191 set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
paulo@0 192 IFS=$oIFS
paulo@0 193
paulo@0 194 pathcomp=''
paulo@0 195
paulo@0 196 while [ $# -ne 0 ] ; do
paulo@0 197 pathcomp=$pathcomp$1
paulo@0 198 shift
paulo@0 199
paulo@0 200 if [ ! -d "$pathcomp" ] ;
paulo@0 201 then
paulo@0 202 $mkdirprog "$pathcomp"
paulo@0 203 else
paulo@0 204 :
paulo@0 205 fi
paulo@0 206
paulo@0 207 pathcomp=$pathcomp/
paulo@0 208 done
paulo@0 209 fi
paulo@0 210
paulo@0 211 if [ x"$dir_arg" != x ]
paulo@0 212 then
paulo@0 213 $doit $instcmd "$dst" &&
paulo@0 214
paulo@0 215 if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi &&
paulo@0 216 if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi &&
paulo@0 217 if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi &&
paulo@0 218 if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi
paulo@0 219 else
paulo@0 220
paulo@0 221 # If we're going to rename the final executable, determine the name now.
paulo@0 222
paulo@0 223 if [ x"$transformarg" = x ]
paulo@0 224 then
paulo@0 225 dstfile=`basename "$dst"`
paulo@0 226 else
paulo@0 227 dstfile=`basename "$dst" $transformbasename |
paulo@0 228 sed $transformarg`$transformbasename
paulo@0 229 fi
paulo@0 230
paulo@0 231 # don't allow the sed command to completely eliminate the filename
paulo@0 232
paulo@0 233 if [ x"$dstfile" = x ]
paulo@0 234 then
paulo@0 235 dstfile=`basename "$dst"`
paulo@0 236 else
paulo@0 237 :
paulo@0 238 fi
paulo@0 239
paulo@0 240 # Make a couple of temp file names in the proper directory.
paulo@0 241
paulo@0 242 dsttmp=$dstdir/_inst.$$_
paulo@0 243 rmtmp=$dstdir/_rm.$$_
paulo@0 244
paulo@0 245 # Trap to clean up temp files at exit.
paulo@0 246
paulo@0 247 trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
paulo@0 248 trap '(exit $?); exit' 1 2 13 15
paulo@0 249
paulo@0 250 # Move or copy the file name to the temp name
paulo@0 251
paulo@0 252 $doit $instcmd "$src" "$dsttmp" &&
paulo@0 253
paulo@0 254 # and set any options; do chmod last to preserve setuid bits
paulo@0 255
paulo@0 256 # If any of these fail, we abort the whole thing. If we want to
paulo@0 257 # ignore errors from any of these, just make sure not to ignore
paulo@0 258 # errors from the above "$doit $instcmd $src $dsttmp" command.
paulo@0 259
paulo@0 260 if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi &&
paulo@0 261 if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi &&
paulo@0 262 if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi &&
paulo@0 263 if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi &&
paulo@0 264
paulo@0 265 # Now remove or move aside any old file at destination location. We try this
paulo@0 266 # two ways since rm can't unlink itself on some systems and the destination
paulo@0 267 # file might be busy for other reasons. In this case, the final cleanup
paulo@0 268 # might fail but the new file should still install successfully.
paulo@0 269
paulo@0 270 {
paulo@0 271 if [ -f "$dstdir/$dstfile" ]
paulo@0 272 then
paulo@0 273 $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null ||
paulo@0 274 $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null ||
paulo@0 275 {
paulo@0 276 echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
paulo@0 277 (exit 1); exit
paulo@0 278 }
paulo@0 279 else
paulo@0 280 :
paulo@0 281 fi
paulo@0 282 } &&
paulo@0 283
paulo@0 284 # Now rename the file to the real destination.
paulo@0 285
paulo@0 286 $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
paulo@0 287
paulo@0 288 fi &&
paulo@0 289
paulo@0 290 # The final little trick to "correctly" pass the exit status to the exit trap.
paulo@0 291
paulo@0 292 {
paulo@0 293 (exit 0); exit
paulo@0 294 }