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