39
39
# when there is no Makefile.
41
41
# This script is compatible with the BSD install script, but was written
42
# from scratch. It can only install one file at a time, a restriction
43
# shared with many OS's install programs.
45
48
# set DOITPROG to echo to test this script
47
50
# Don't use :- since 4.3BSD and earlier shells don't like it.
50
# put in absolute paths if you don't have them in your path; or use env. vars.
54
chmodprog="${CHMODPROG-chmod}"
55
chownprog="${CHOWNPROG-chown}"
56
chgrpprog="${CHGRPPROG-chgrp}"
57
stripprog="${STRIPPROG-strip}"
59
mkdirprog="${MKDIRPROG-mkdir}"
64
chmodcmd="$chmodprog 0755"
52
if test -z "$doit"; then
58
# Put in absolute file names if you don't have them in your path;
59
# or use environment vars.
61
chgrpprog=${CHGRPPROG-chgrp}
62
chmodprog=${CHMODPROG-chmod}
63
chownprog=${CHOWNPROG-chown}
64
cmpprog=${CMPPROG-cmp}
66
mkdirprog=${MKDIRPROG-mkdir}
69
stripprog=${STRIPPROG-strip}
72
initialize_posix_glob='
73
test "$posix_glob" != "?" || {
74
if (set -f) 2>/dev/null; then
84
# Desired mode of installed file.
74
usage="Usage: $0 [OPTION]... SRCFILE DSTFILE
103
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
75
104
or: $0 [OPTION]... SRCFILES... DIRECTORY
76
or: $0 -d DIRECTORIES...
105
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
106
or: $0 [OPTION]... -d DIRECTORIES...
78
In the first form, install SRCFILE to DSTFILE, removing SRCFILE by default.
79
In the second, create the directory path DIR.
108
In the 1st form, copy SRCFILE to DSTFILE.
109
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
110
In the 4th, create DIRECTORIES.
83
-c copy source (using $cpprog) instead of moving (using $mvprog).
84
-d create directories instead of installing files.
85
-g GROUP $chgrp installed files to GROUP.
86
-m MODE $chmod installed files to MODE.
87
-o USER $chown installed files to USER.
88
-s strip installed files (using $stripprog).
90
--help display this help and exit.
91
--version display version info and exit.
113
--help display this help and exit.
114
--version display version info and exit.
117
-C install only if different (preserve the last data modification time)
118
-d create directories instead of installing files.
119
-g GROUP $chgrpprog installed files to GROUP.
120
-m MODE $chmodprog installed files to MODE.
121
-o USER $chownprog installed files to USER.
122
-s $stripprog installed files.
123
-t DIRECTORY install into DIRECTORY.
124
-T report an error if DSTFILE is a directory.
93
126
Environment variables override the default commands:
94
CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
127
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
97
while test -n "$1"; do
131
while test $# -ne 0; do
99
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
135
-C) copy_on_change=true;;
111
139
-g) chgrpcmd="$chgrpprog $2"
116
--help) echo "$usage"; exit 0;;
118
-m) chmodcmd="$chmodprog $2"
142
--help) echo "$usage"; exit $?;;
147
'* | *'*'* | *'?'* | *'['*)
148
echo "$0: invalid mode: $mode" >&2
123
153
-o) chowncmd="$chownprog $2"
128
-s) stripcmd=$stripprog
132
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
136
--version) echo "$0 $scriptversion"; exit 0;;
138
*) # When -d is used, all remaining arguments are directories to create.
139
test -n "$dir_arg" && break
140
# Otherwise, the last argument is the destination. Remove it from $@.
143
if test -n "$dstarg"; then
144
# $@ is not empty: it contains at least $arg.
145
set fnord "$@" "$dstarg"
156
-s) stripcmd=$stripprog;;
161
-T) no_target_directory=true;;
163
--version) echo "$0 $scriptversion"; exit $?;;
168
-*) echo "$0: invalid option: $1" >&2
155
if test -z "$1"; then
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 $@.
182
if test -n "$dst_arg"; then
183
# $@ is not empty: it contains at least $arg.
184
set fnord "$@" "$dst_arg"
192
if test $# -eq 0; then
156
193
if test -z "$dir_arg"; then
157
194
echo "$0: no input file specified." >&2
191
if test -z "$dstarg"; then
251
if test -z "$dst_arg"; then
192
252
echo "$0: no destination specified." >&2
197
257
# Protect names starting with `-'.
202
262
# If destination is a directory, append the input filename; won't work
203
263
# if double slashes aren't ignored.
204
264
if test -d "$dst"; then
205
dst=$dst/`basename "$src"`
265
if test -n "$no_target_directory"; then
266
echo "$0: $dst_arg: Is a directory" >&2
270
dst=$dstdir/`basename "$src"`
273
# Prefer dirname, but fall back on a substitute if dirname fails.
275
(dirname "$dst") 2>/dev/null ||
276
expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
277
X"$dst" : 'X\(//\)[^/]' \| \
278
X"$dst" : 'X\(//\)$' \| \
279
X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
281
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
209
# This sed command emulates the dirname command.
210
dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
212
# Make sure that the destination directory exists.
214
# Skip lots of stat calls in the usual case.
215
if test ! -d "$dstdir"; then
218
IFS="${IFS-$defaultIFS}"
221
# Some sh's can't handle IFS=/ for some reason.
223
set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
228
while test $# -ne 0 ; do
305
obsolete_mkdir_used=false
307
if test $dstdir_status != 0; then
310
# Create intermediate dirs using mode 755 as modified by the umask.
311
# This is like FreeBSD 'install' as of 1997-10-28.
313
case $stripcmd.$umask in
314
# Optimize common cases.
315
*[2367][2367]) mkdir_umask=$umask;;
316
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
319
mkdir_umask=`expr $umask + 22 \
320
- $umask % 100 % 40 + $umask % 20 \
321
- $umask % 10 % 4 + $umask % 2
323
*) mkdir_umask=$umask,go-w;;
326
# With -d, create the new directory with the user-specified mode.
327
# Otherwise, rely on $mkdir_umask.
328
if test -n "$dir_arg"; then
337
# POSIX mkdir -p sets u+wx bits regardless of umask, which
338
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
341
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
342
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
344
if (umask $mkdir_umask &&
345
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
347
if test -z "$dir_arg" || {
348
# Check for POSIX incompatibilities with -m.
349
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
350
# other-writeable bit of parent directory when it shouldn't.
351
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
352
ls_ld_tmpdir=`ls -ld "$tmpdir"`
353
case $ls_ld_tmpdir in
354
d????-?r-*) different_mode=700;;
355
d????-?--*) different_mode=755;;
358
$mkdirprog -m$different_mode -p -- "$tmpdir" && {
359
ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
360
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
365
rmdir "$tmpdir/d" "$tmpdir"
367
# Remove any dirs left behind by ancient mkdir implementations.
368
rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
376
umask $mkdir_umask &&
377
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
382
# The umask is ridiculous, or mkdir does not conform to POSIX,
383
# or it failed possibly due to a race condition. Create the
384
# directory the slow way, step by step, checking for races as we go.
392
eval "$initialize_posix_glob"
231
if test ! -d "$pathcomp"; then
232
$mkdirprog "$pathcomp" || lasterr=$?
233
# mkdir can fail with a `File exist' error in case several
234
# install-sh are creating the directory concurrently. This
236
test ! -d "$pathcomp" && { (exit ${lasterr-1}); exit; }
406
test -z "$d" && continue
409
if test -d "$prefix"; then
412
if $posix_mkdir; then
413
(umask=$mkdir_umask &&
414
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
415
# Don't fail if two instances are running concurrently.
416
test -d "$prefix" || exit 1
419
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
422
prefixes="$prefixes '$qprefix'"
428
if test -n "$prefixes"; then
429
# Don't fail if two instances are running concurrently.
430
(umask $mkdir_umask &&
431
eval "\$doit_exec \$mkdirprog $prefixes") ||
432
test -d "$dstdir" || exit 1
433
obsolete_mkdir_used=true
242
438
if test -n "$dir_arg"; then
243
$doit $instcmd "$dst" \
244
&& { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
245
&& { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
246
&& { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
247
&& { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
439
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
440
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
441
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
442
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
250
# If we're going to rename the final executable, determine the name now.
251
if test -z "$transformarg"; then
252
dstfile=`basename "$dst"`
254
dstfile=`basename "$dst" $transformbasename \
255
| sed $transformarg`$transformbasename
258
# don't allow the sed command to completely eliminate the filename.
259
test -z "$dstfile" && dstfile=`basename "$dst"`
261
445
# Make a couple of temp file names in the proper directory.
262
446
dsttmp=$dstdir/_inst.$$_
263
447
rmtmp=$dstdir/_rm.$$_
265
449
# Trap to clean up those temp files at exit.
266
trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
267
trap '(exit $?); exit' 1 2 13 15
450
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
269
# Move or copy the file name to the temp name
270
$doit $instcmd "$src" "$dsttmp" &&
452
# Copy the file name to the temp name.
453
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
272
455
# and set any options; do chmod last to preserve setuid bits.
274
457
# If any of these fail, we abort the whole thing. If we want to
275
458
# ignore errors from any of these, just make sure not to ignore
276
# errors from the above "$doit $instcmd $src $dsttmp" command.
459
# errors from the above "$doit $cpprog $src $dsttmp" command.
278
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
279
&& { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
280
&& { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
281
&& { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
283
# Now remove or move aside any old file at destination location. We
284
# try this two ways since rm can't unlink itself on some systems and
285
# the destination file might be busy for other reasons. In this case,
286
# the final cleanup might fail but the new file should still install
289
if test -f "$dstdir/$dstfile"; then
290
$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
291
|| $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
293
echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
301
# Now rename the file to the real destination.
302
$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
303
fi || { (exit 1); exit; }
461
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
462
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
463
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
464
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
466
# If -C, don't bother to copy if it wouldn't change the file.
467
if $copy_on_change &&
468
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
469
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
471
eval "$initialize_posix_glob" &&
472
$posix_glob set -f &&
473
set X $old && old=:$2:$4:$5:$6 &&
474
set X $new && new=:$2:$4:$5:$6 &&
475
$posix_glob set +f &&
477
test "$old" = "$new" &&
478
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
482
# Rename the file to the real destination.
483
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
485
# The rename failed, perhaps because mv can't rename something else
486
# to itself, or perhaps because mv is so ancient that it does not
489
# Now remove or move aside any old file at destination location.
490
# We try this two ways since rm can't unlink itself on some
491
# systems and the destination file might be busy for other
492
# reasons. In this case, the final cleanup might fail but the new
493
# file should still install successfully.
496
$doit $rmcmd -f "$dst" 2>/dev/null ||
497
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
498
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
500
{ echo "$0: cannot unlink or rename $dst" >&2
505
# Now rename the file to the real destination.
506
$doit $mvcmd "$dsttmp" "$dst"
306
# The final little trick to "correctly" pass the exit status to the exit trap.
311
514
# Local variables:
312
515
# eval: (add-hook 'write-file-hooks 'time-stamp)
313
516
# time-stamp-start: "scriptversion="
314
517
# time-stamp-format: "%:y-%02m-%02d.%02H"
315
# time-stamp-end: "$"
518
# time-stamp-time-zone: "UTC"
519
# time-stamp-end: "; # UTC"