xref: /netbsd-src/external/bsd/file/dist/install-sh (revision c20607ae2bc2c5e627d3fb605d76ed2891f0dfd2)
1*c20607aeSchristos#!/bin/sh
2*c20607aeSchristos#
3*c20607aeSchristos# $NetBSD: install-sh,v 1.14 2022/09/24 20:33:29 christos Exp $
4*c20607aeSchristos# This script now also installs multiple files, but might choke on installing
5*c20607aeSchristos# multiple files with spaces in the file names.
6*c20607aeSchristos#
7*c20607aeSchristos# install - install a program, script, or datafile
8*c20607aeSchristos# This comes from X11R5 (mit/util/scripts/install.sh).
9*c20607aeSchristos#
10*c20607aeSchristos# Copyright 1991 by the Massachusetts Institute of Technology
11*c20607aeSchristos#
12*c20607aeSchristos# Permission to use, copy, modify, distribute, and sell this software and its
13*c20607aeSchristos# documentation for any purpose is hereby granted without fee, provided that
14*c20607aeSchristos# the above copyright notice appear in all copies and that both that
15*c20607aeSchristos# copyright notice and this permission notice appear in supporting
16*c20607aeSchristos# documentation, and that the name of M.I.T. not be used in advertising or
17*c20607aeSchristos# publicity pertaining to distribution of the software without specific,
18*c20607aeSchristos# written prior permission.  M.I.T. makes no representations about the
19*c20607aeSchristos# suitability of this software for any purpose.  It is provided "as is"
20*c20607aeSchristos# without express or implied warranty.
21*c20607aeSchristos#
22*c20607aeSchristos# Calling this script install-sh is preferred over install.sh, to prevent
23*c20607aeSchristos# `make' implicit rules from creating a file called install from it
24*c20607aeSchristos# when there is no Makefile.
25*c20607aeSchristos#
26*c20607aeSchristos# This script is compatible with the BSD install script, but was written
27*c20607aeSchristos# from scratch.
28*c20607aeSchristos
29*c20607aeSchristos# set DOITPROG to echo to test this script
30*c20607aeSchristos
31*c20607aeSchristos# Don't use :- since 4.3BSD and earlier shells don't like it.
32*c20607aeSchristosdoit="${DOITPROG-}"
33*c20607aeSchristos
34*c20607aeSchristos
35*c20607aeSchristos# put in absolute paths if you don't have them in your path; or use env. vars.
36*c20607aeSchristos
37*c20607aeSchristosawkprog="${AWKPROG-awk}"
38*c20607aeSchristosmvprog="${MVPROG-mv}"
39*c20607aeSchristoscpprog="${CPPROG-cp}"
40*c20607aeSchristoschmodprog="${CHMODPROG-chmod}"
41*c20607aeSchristoschownprog="${CHOWNPROG-chown}"
42*c20607aeSchristoschgrpprog="${CHGRPPROG-chgrp}"
43*c20607aeSchristosstripprog="${STRIPPROG-strip}"
44*c20607aeSchristosrmprog="${RMPROG-rm}"
45*c20607aeSchristosmkdirprog="${MKDIRPROG-mkdir}"
46*c20607aeSchristos
47*c20607aeSchristosinstcmd="$cpprog"
48*c20607aeSchristosinstflags=""
49*c20607aeSchristospathcompchmodcmd="$chmodprog 755"
50*c20607aeSchristoschmodcmd="$chmodprog 755"
51*c20607aeSchristoschowncmd=""
52*c20607aeSchristoschgrpcmd=""
53*c20607aeSchristosstripcmd=""
54*c20607aeSchristosstripflags=""
55*c20607aeSchristosrmcmd="$rmprog -f"
56*c20607aeSchristosmvcmd="$mvprog"
57*c20607aeSchristossrc=""
58*c20607aeSchristosmsrc=""
59*c20607aeSchristosdst=""
60*c20607aeSchristosdir_arg=""
61*c20607aeSchristossuffix=""
62*c20607aeSchristossuffixfmt=""
63*c20607aeSchristos
64*c20607aeSchristoswhile [ x"$1" != x ]; do
65*c20607aeSchristos    case $1 in
66*c20607aeSchristos	-b) suffix=".old"
67*c20607aeSchristos	    shift
68*c20607aeSchristos	    continue;;
69*c20607aeSchristos
70*c20607aeSchristos	-B) suffixfmt="$2"
71*c20607aeSchristos	    shift
72*c20607aeSchristos	    shift
73*c20607aeSchristos	    continue;;
74*c20607aeSchristos
75*c20607aeSchristos	-c) instcmd="$cpprog"
76*c20607aeSchristos	    shift
77*c20607aeSchristos	    continue;;
78*c20607aeSchristos
79*c20607aeSchristos	-d) dir_arg=true
80*c20607aeSchristos	    shift
81*c20607aeSchristos	    continue;;
82*c20607aeSchristos
83*c20607aeSchristos	-m) chmodcmd="$chmodprog $2"
84*c20607aeSchristos	    shift
85*c20607aeSchristos	    shift
86*c20607aeSchristos	    continue;;
87*c20607aeSchristos
88*c20607aeSchristos	-m*)
89*c20607aeSchristos	    chmodcmd="$chmodprog ${1#-m}"
90*c20607aeSchristos	    shift
91*c20607aeSchristos	    continue;;
92*c20607aeSchristos
93*c20607aeSchristos	-o) chowncmd="$chownprog $2"
94*c20607aeSchristos	    shift
95*c20607aeSchristos	    shift
96*c20607aeSchristos	    continue;;
97*c20607aeSchristos
98*c20607aeSchristos	-g) chgrpcmd="$chgrpprog $2"
99*c20607aeSchristos	    shift
100*c20607aeSchristos	    shift
101*c20607aeSchristos	    continue;;
102*c20607aeSchristos
103*c20607aeSchristos	-s) stripcmd="$stripprog"
104*c20607aeSchristos	    shift
105*c20607aeSchristos	    continue;;
106*c20607aeSchristos
107*c20607aeSchristos	-S) stripcmd="$stripprog"
108*c20607aeSchristos	    stripflags="-S $2 $stripflags"
109*c20607aeSchristos	    shift
110*c20607aeSchristos	    shift
111*c20607aeSchristos	    continue;;
112*c20607aeSchristos
113*c20607aeSchristos	-p) instflags="-p"
114*c20607aeSchristos	    shift
115*c20607aeSchristos	    continue;;
116*c20607aeSchristos
117*c20607aeSchristos	*)  if [ x"$msrc" = x ]
118*c20607aeSchristos	    then
119*c20607aeSchristos		msrc="$dst"
120*c20607aeSchristos	    else
121*c20607aeSchristos		msrc="$msrc $dst"
122*c20607aeSchristos	    fi
123*c20607aeSchristos	    src="$dst"
124*c20607aeSchristos	    dst="$1"
125*c20607aeSchristos	    shift
126*c20607aeSchristos	    continue;;
127*c20607aeSchristos    esac
128*c20607aeSchristosdone
129*c20607aeSchristos
130*c20607aeSchristosif [ x"$dir_arg" = x ]
131*c20607aeSchristosthen
132*c20607aeSchristos	dstisfile=""
133*c20607aeSchristos	if [ ! -d "$dst" ]
134*c20607aeSchristos	then
135*c20607aeSchristos		if [ x"$msrc" = x"$src" ]
136*c20607aeSchristos		then
137*c20607aeSchristos			dstisfile=true
138*c20607aeSchristos		else
139*c20607aeSchristos			echo "install: destination is not a directory"
140*c20607aeSchristos			exit 1
141*c20607aeSchristos		fi
142*c20607aeSchristos	fi
143*c20607aeSchristoselse
144*c20607aeSchristos	msrc="$msrc $dst"
145*c20607aeSchristosfi
146*c20607aeSchristos
147*c20607aeSchristosif [ x"$msrc" = x ]
148*c20607aeSchristosthen
149*c20607aeSchristos	echo "install: no destination specified"
150*c20607aeSchristos	exit 1
151*c20607aeSchristosfi
152*c20607aeSchristos
153*c20607aeSchristosfor srcarg in $msrc; do
154*c20607aeSchristos
155*c20607aeSchristosif [ x"$dir_arg" != x ]; then
156*c20607aeSchristos
157*c20607aeSchristos	dstarg="$srcarg"
158*c20607aeSchristoselse
159*c20607aeSchristos	dstarg="$dst"
160*c20607aeSchristos
161*c20607aeSchristos# Waiting for this to be detected by the "$instcmd $srcarg $dsttmp" command
162*c20607aeSchristos# might cause directories to be created, which would be especially bad
163*c20607aeSchristos# if $src (and thus $dsttmp) contains '*'.
164*c20607aeSchristos
165*c20607aeSchristos	if [ -f "$srcarg" ]
166*c20607aeSchristos	then
167*c20607aeSchristos		doinst="$instcmd $instflags"
168*c20607aeSchristos	elif [ -d "$srcarg" ]
169*c20607aeSchristos	then
170*c20607aeSchristos		echo "install: $srcarg: not a regular file"
171*c20607aeSchristos		exit 1
172*c20607aeSchristos	elif [ "$srcarg" = "/dev/null" ]
173*c20607aeSchristos	then
174*c20607aeSchristos		doinst="$cpprog"
175*c20607aeSchristos	else
176*c20607aeSchristos		echo "install:  $srcarg does not exist"
177*c20607aeSchristos		exit 1
178*c20607aeSchristos	fi
179*c20607aeSchristos
180*c20607aeSchristos# If destination is a directory, append the input filename; if your system
181*c20607aeSchristos# does not like double slashes in filenames, you may need to add some logic
182*c20607aeSchristos
183*c20607aeSchristos	if [ -d "$dstarg" ]
184*c20607aeSchristos	then
185*c20607aeSchristos		dstarg="$dstarg"/`basename "$srcarg"`
186*c20607aeSchristos	fi
187*c20607aeSchristosfi
188*c20607aeSchristos
189*c20607aeSchristos## this sed command emulates the dirname command
190*c20607aeSchristosdstdir=`echo "$dstarg" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
191*c20607aeSchristos
192*c20607aeSchristos# Make sure that the destination directory exists.
193*c20607aeSchristos#  this part is taken from Noah Friedman's mkinstalldirs script
194*c20607aeSchristos
195*c20607aeSchristos# Skip lots of stat calls in the usual case.
196*c20607aeSchristosif [ ! -d "$dstdir" ]; then
197*c20607aeSchristosdefaultIFS='
198*c20607aeSchristos'
199*c20607aeSchristosIFS="${IFS-${defaultIFS}}"
200*c20607aeSchristos
201*c20607aeSchristosoIFS="${IFS}"
202*c20607aeSchristos# Some sh's can't handle IFS=/ for some reason.
203*c20607aeSchristosIFS='%'
204*c20607aeSchristosset - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
205*c20607aeSchristosIFS="${oIFS}"
206*c20607aeSchristos
207*c20607aeSchristospathcomp=''
208*c20607aeSchristos
209*c20607aeSchristoswhile [ $# -ne 0 ] ; do
210*c20607aeSchristos	pathcomp="${pathcomp}${1}"
211*c20607aeSchristos	shift
212*c20607aeSchristos
213*c20607aeSchristos	if [ ! -d "${pathcomp}" ] ;
214*c20607aeSchristos        then
215*c20607aeSchristos		$doit $mkdirprog "${pathcomp}"
216*c20607aeSchristos        	if [ x"$chowncmd" != x ]; then $doit $chowncmd "${pathcomp}"; else true ; fi &&
217*c20607aeSchristos        	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "${pathcomp}"; else true ; fi &&
218*c20607aeSchristos        	if [ x"$pathcompchmodcmd" != x ]; then $doit $pathcompchmodcmd "${pathcomp}"; else true ; fi
219*c20607aeSchristos
220*c20607aeSchristos	else
221*c20607aeSchristos		true
222*c20607aeSchristos	fi
223*c20607aeSchristos
224*c20607aeSchristos	pathcomp="${pathcomp}/"
225*c20607aeSchristosdone
226*c20607aeSchristosfi
227*c20607aeSchristos
228*c20607aeSchristos	if [ x"$dir_arg" != x ]
229*c20607aeSchristos	then
230*c20607aeSchristos		if [ -d "$dstarg" ]; then
231*c20607aeSchristos			true
232*c20607aeSchristos		else
233*c20607aeSchristos			$doit $mkdirprog "$dstarg" &&
234*c20607aeSchristos
235*c20607aeSchristos			if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dstarg"; else true ; fi &&
236*c20607aeSchristos			if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dstarg"; else true ; fi &&
237*c20607aeSchristos			if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dstarg"; else true ; fi
238*c20607aeSchristos		fi
239*c20607aeSchristos	else
240*c20607aeSchristos
241*c20607aeSchristos		if [ x"$dstisfile" = x ]
242*c20607aeSchristos		then
243*c20607aeSchristos			file=$srcarg
244*c20607aeSchristos		else
245*c20607aeSchristos			file=$dst
246*c20607aeSchristos		fi
247*c20607aeSchristos
248*c20607aeSchristos		dstfile=`basename "$file"`
249*c20607aeSchristos		dstfinal="$dstdir/$dstfile"
250*c20607aeSchristos
251*c20607aeSchristos# Make a temp file name in the proper directory.
252*c20607aeSchristos
253*c20607aeSchristos		dsttmp=$dstdir/#inst.$$#
254*c20607aeSchristos
255*c20607aeSchristos# Make a backup file name in the proper directory.
256*c20607aeSchristos		case x$suffixfmt in
257*c20607aeSchristos		*%*)	suffix=`echo x |
258*c20607aeSchristos			$awkprog -v bname="$dstfinal" -v fmt="$suffixfmt" '
259*c20607aeSchristos			{ cnt = 0;
260*c20607aeSchristos			  do {
261*c20607aeSchristos				sfx = sprintf(fmt, cnt++);
262*c20607aeSchristos				name = bname sfx;
263*c20607aeSchristos			  } while (system("test -f " name) == 0);
264*c20607aeSchristos			  print sfx; }' -`;;
265*c20607aeSchristos		x)	;;
266*c20607aeSchristos		*)	suffix="$suffixfmt";;
267*c20607aeSchristos		esac
268*c20607aeSchristos		dstbackup="$dstfinal$suffix"
269*c20607aeSchristos
270*c20607aeSchristos# Move or copy the file name to the temp name
271*c20607aeSchristos
272*c20607aeSchristos		$doit $doinst $srcarg "$dsttmp" &&
273*c20607aeSchristos
274*c20607aeSchristos		trap "rm -f ${dsttmp}" 0 &&
275*c20607aeSchristos
276*c20607aeSchristos# and set any options; do chmod last to preserve setuid bits
277*c20607aeSchristos
278*c20607aeSchristos# If any of these fail, we abort the whole thing.  If we want to
279*c20607aeSchristos# ignore errors from any of these, just make sure not to ignore
280*c20607aeSchristos# errors from the above "$doit $instcmd $src $dsttmp" command.
281*c20607aeSchristos
282*c20607aeSchristos		if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else true;fi &&
283*c20607aeSchristos		if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else true;fi &&
284*c20607aeSchristos		if [ x"$stripcmd" != x ]; then $doit $stripcmd $stripflags "$dsttmp"; else true;fi &&
285*c20607aeSchristos		if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else true;fi &&
286*c20607aeSchristos
287*c20607aeSchristos# Now rename the file to the real destination.
288*c20607aeSchristos
289*c20607aeSchristos		if [ x"$suffix" != x ] && [ -f "$dstfinal" ]
290*c20607aeSchristos		then
291*c20607aeSchristos			$doit $mvcmd "$dstfinal" "$dstbackup"
292*c20607aeSchristos		else
293*c20607aeSchristos			$doit $rmcmd -f "$dstfinal"
294*c20607aeSchristos		fi &&
295*c20607aeSchristos		$doit $mvcmd "$dsttmp" "$dstfinal"
296*c20607aeSchristos	fi
297*c20607aeSchristos
298*c20607aeSchristosdone &&
299*c20607aeSchristos
300*c20607aeSchristos
301*c20607aeSchristosexit 0
302