1 |
#!/bin/sh |
#!/bin/sh |
2 |
# install - install a program, script, or datafile |
# install - install a program, script, or datafile |
3 |
|
|
4 |
scriptversion=2005-02-02.21 |
scriptversion=2005-09-13.16 |
5 |
|
|
6 |
# This originates from X11R5 (mit/util/scripts/install.sh), which was |
# This originates from X11R5 (mit/util/scripts/install.sh), which was |
7 |
# later released in X11R6 (xc/config/util/install.sh) with the |
# later released in X11R6 (xc/config/util/install.sh) with the |
58 |
rmprog="${RMPROG-rm}" |
rmprog="${RMPROG-rm}" |
59 |
mkdirprog="${MKDIRPROG-mkdir}" |
mkdirprog="${MKDIRPROG-mkdir}" |
60 |
|
|
61 |
chmodcmd="$chmodprog 0755" |
posix_glob= |
62 |
|
posix_mkdir= |
63 |
|
|
64 |
|
# Symbolic mode for testing mkdir with directories. |
65 |
|
# It is the same as 755, but also tests that "u+" works. |
66 |
|
test_mode=u=rwx,g=rx,o=rx,u+wx |
67 |
|
|
68 |
|
# Desired mode of installed file. |
69 |
|
mode=0755 |
70 |
|
|
71 |
|
# Desired mode of newly created intermediate directories. |
72 |
|
# It is empty if not known yet. |
73 |
|
intermediate_mode= |
74 |
|
|
75 |
|
chmodcmd=$chmodprog |
76 |
chowncmd= |
chowncmd= |
77 |
chgrpcmd= |
chgrpcmd= |
78 |
stripcmd= |
stripcmd= |
125 |
|
|
126 |
--help) echo "$usage"; exit $?;; |
--help) echo "$usage"; exit $?;; |
127 |
|
|
128 |
-m) chmodcmd="$chmodprog $2" |
-m) mode=$2 |
129 |
shift |
shift |
130 |
shift |
shift |
131 |
continue;; |
continue;; |
178 |
exit 0 |
exit 0 |
179 |
fi |
fi |
180 |
|
|
181 |
|
test -n "$dir_arg" || trap '(exit $?); exit' 1 2 13 15 |
182 |
|
|
183 |
for src |
for src |
184 |
do |
do |
185 |
# Protect names starting with `-'. |
# Protect names starting with `-'. |
189 |
|
|
190 |
if test -n "$dir_arg"; then |
if test -n "$dir_arg"; then |
191 |
dst=$src |
dst=$src |
192 |
src= |
dstdir=$dst |
193 |
|
test -d "$dstdir" |
194 |
if test -d "$dst"; then |
dstdir_status=$? |
|
mkdircmd=: |
|
|
chmodcmd= |
|
|
else |
|
|
mkdircmd=$mkdirprog |
|
|
fi |
|
195 |
else |
else |
196 |
|
|
197 |
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command |
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command |
198 |
# might cause directories to be created, which would be especially bad |
# might cause directories to be created, which would be especially bad |
199 |
# if $src (and thus $dsttmp) contains '*'. |
# if $src (and thus $dsttmp) contains '*'. |
220 |
echo "$0: $dstarg: Is a directory" >&2 |
echo "$0: $dstarg: Is a directory" >&2 |
221 |
exit 1 |
exit 1 |
222 |
fi |
fi |
223 |
dst=$dst/`basename "$src"` |
dstdir=$dst |
224 |
|
dst=$dstdir/`basename "$src"` |
225 |
|
dstdir_status=0 |
226 |
|
else |
227 |
|
# Prefer dirname, but fall back on a substitute if dirname fails. |
228 |
|
dstdir=` |
229 |
|
(dirname "$dst") 2>/dev/null || |
230 |
|
expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ |
231 |
|
X"$dst" : 'X\(//\)[^/]' \| \ |
232 |
|
X"$dst" : 'X\(//\)$' \| \ |
233 |
|
X"$dst" : 'X\(/\)' \| \ |
234 |
|
. : '\(.\)' 2>/dev/null || |
235 |
|
echo X"$dst" | |
236 |
|
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } |
237 |
|
/^X\(\/\/\)[^/].*/{ s//\1/; q; } |
238 |
|
/^X\(\/\/\)$/{ s//\1/; q; } |
239 |
|
/^X\(\/\).*/{ s//\1/; q; } |
240 |
|
s/.*/./; q' |
241 |
|
` |
242 |
|
|
243 |
|
test -d "$dstdir" |
244 |
|
dstdir_status=$? |
245 |
fi |
fi |
246 |
fi |
fi |
247 |
|
|
248 |
# This sed command emulates the dirname command. |
obsolete_mkdir_used=false |
|
dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` |
|
249 |
|
|
250 |
# Make sure that the destination directory exists. |
if test $dstdir_status != 0; then |
251 |
|
case $posix_mkdir in |
252 |
|
'') |
253 |
|
posix_mkdir=false |
254 |
|
if $mkdirprog -m $test_mode -p -- / >/dev/null 2>&1; then |
255 |
|
posix_mkdir=true |
256 |
|
else |
257 |
|
# Remove any dirs left behind by ancient mkdir implementations. |
258 |
|
rmdir ./-m "$test_mode" ./-p ./-- 2>/dev/null |
259 |
|
fi ;; |
260 |
|
esac |
261 |
|
|
262 |
# Skip lots of stat calls in the usual case. |
if |
263 |
if test ! -d "$dstdir"; then |
$posix_mkdir && { |
|
defaultIFS=' |
|
|
' |
|
|
IFS="${IFS-$defaultIFS}" |
|
|
|
|
|
oIFS=$IFS |
|
|
# Some sh's can't handle IFS=/ for some reason. |
|
|
IFS='%' |
|
|
set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` |
|
|
shift |
|
|
IFS=$oIFS |
|
264 |
|
|
265 |
pathcomp= |
# With -d, create the new directory with the user-specified mode. |
266 |
|
# Otherwise, create it using the same intermediate mode that |
267 |
|
# mkdir -p would use when creating intermediate directories. |
268 |
|
# POSIX says that this mode is "$(umask -S),u+wx", so use that |
269 |
|
# if umask -S works. |
270 |
|
|
271 |
|
if test -n "$dir_arg"; then |
272 |
|
mkdir_mode=$mode |
273 |
|
else |
274 |
|
case $intermediate_mode in |
275 |
|
'') |
276 |
|
if umask_S=`(umask -S) 2>/dev/null`; then |
277 |
|
intermediate_mode=$umask_S,u+wx |
278 |
|
else |
279 |
|
intermediate_mode=$test_mode |
280 |
|
fi ;; |
281 |
|
esac |
282 |
|
mkdir_mode=$intermediate_mode |
283 |
|
fi |
284 |
|
|
285 |
|
$mkdirprog -m "$mkdir_mode" -p -- "$dstdir" |
286 |
|
} |
287 |
|
then : |
288 |
|
else |
289 |
|
|
290 |
while test $# -ne 0 ; do |
# mkdir does not conform to POSIX, or it failed possibly due to |
291 |
pathcomp=$pathcomp$1 |
# a race condition. Create the directory the slow way, step by |
292 |
|
# step, checking for races as we go. |
293 |
|
|
294 |
|
case $dstdir in |
295 |
|
/*) pathcomp=/ ;; |
296 |
|
-*) pathcomp=./ ;; |
297 |
|
*) pathcomp= ;; |
298 |
|
esac |
299 |
|
|
300 |
|
case $posix_glob in |
301 |
|
'') |
302 |
|
if (set -f) 2>/dev/null; then |
303 |
|
posix_glob=true |
304 |
|
else |
305 |
|
posix_glob=false |
306 |
|
fi ;; |
307 |
|
esac |
308 |
|
|
309 |
|
oIFS=$IFS |
310 |
|
IFS=/ |
311 |
|
$posix_glob && set -f |
312 |
|
set fnord $dstdir |
313 |
shift |
shift |
314 |
if test ! -d "$pathcomp"; then |
$posix_glob && set +f |
315 |
$mkdirprog "$pathcomp" |
IFS=$oIFS |
316 |
# mkdir can fail with a `File exist' error in case several |
|
317 |
# install-sh are creating the directory concurrently. This |
for d |
318 |
# is OK. |
do |
319 |
test -d "$pathcomp" || exit |
test "x$d" = x && continue |
320 |
fi |
|
321 |
pathcomp=$pathcomp/ |
pathcomp=$pathcomp$d |
322 |
done |
if test ! -d "$pathcomp"; then |
323 |
|
$mkdirprog "$pathcomp" |
324 |
|
# Don't fail if two instances are running concurrently. |
325 |
|
test -d "$pathcomp" || exit 1 |
326 |
|
fi |
327 |
|
pathcomp=$pathcomp/ |
328 |
|
done |
329 |
|
obsolete_mkdir_used=true |
330 |
|
fi |
331 |
fi |
fi |
332 |
|
|
333 |
if test -n "$dir_arg"; then |
if test -n "$dir_arg"; then |
334 |
$doit $mkdircmd "$dst" \ |
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } && |
335 |
&& { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ |
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && |
336 |
&& { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ |
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || |
337 |
&& { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ |
test -z "$chmodcmd" || $doit $chmodcmd "$mode" "$dst"; } || exit 1 |
|
&& { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } |
|
|
|
|
338 |
else |
else |
|
dstfile=`basename "$dst"` |
|
339 |
|
|
340 |
# Make a couple of temp file names in the proper directory. |
# Make a couple of temp file names in the proper directory. |
341 |
dsttmp=$dstdir/_inst.$$_ |
dsttmp=$dstdir/_inst.$$_ |
343 |
|
|
344 |
# Trap to clean up those temp files at exit. |
# Trap to clean up those temp files at exit. |
345 |
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 |
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 |
|
trap '(exit $?); exit' 1 2 13 15 |
|
346 |
|
|
347 |
# Copy the file name to the temp name. |
# Copy the file name to the temp name. |
348 |
$doit $cpprog "$src" "$dsttmp" && |
$doit $cpprog "$src" "$dsttmp" && |
356 |
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ |
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ |
357 |
&& { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ |
&& { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ |
358 |
&& { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ |
&& { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ |
359 |
&& { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && |
&& { test -z "$chmodcmd" || $doit $chmodcmd "$mode" "$dsttmp"; } && |
360 |
|
|
361 |
# Now rename the file to the real destination. |
# Now rename the file to the real destination. |
362 |
{ $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ |
{ $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null \ |
363 |
|| { |
|| { |
364 |
# The rename failed, perhaps because mv can't rename something else |
# The rename failed, perhaps because mv can't rename something else |
365 |
# to itself, or perhaps because mv is so ancient that it does not |
# to itself, or perhaps because mv is so ancient that it does not |
371 |
# reasons. In this case, the final cleanup might fail but the new |
# reasons. In this case, the final cleanup might fail but the new |
372 |
# file should still install successfully. |
# file should still install successfully. |
373 |
{ |
{ |
374 |
if test -f "$dstdir/$dstfile"; then |
if test -f "$dst"; then |
375 |
$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ |
$doit $rmcmd -f "$dst" 2>/dev/null \ |
376 |
|| $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ |
|| { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null \ |
377 |
|
&& { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }; }\ |
378 |
|| { |
|| { |
379 |
echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 |
echo "$0: cannot unlink or rename $dst" >&2 |
380 |
(exit 1); exit 1 |
(exit 1); exit 1 |
381 |
} |
} |
382 |
else |
else |
385 |
} && |
} && |
386 |
|
|
387 |
# Now rename the file to the real destination. |
# Now rename the file to the real destination. |
388 |
$doit $mvcmd "$dsttmp" "$dstdir/$dstfile" |
$doit $mvcmd "$dsttmp" "$dst" |
389 |
} |
} |
390 |
} |
} || exit 1 |
|
fi || { (exit 1); exit 1; } |
|
|
done |
|
391 |
|
|
392 |
# The final little trick to "correctly" pass the exit status to the exit trap. |
trap - 0 |
393 |
{ |
fi |
394 |
(exit 0); exit 0 |
done |
|
} |
|
395 |
|
|
396 |
# Local variables: |
# Local variables: |
397 |
# eval: (add-hook 'write-file-hooks 'time-stamp) |
# eval: (add-hook 'write-file-hooks 'time-stamp) |