xref: /freebsd/contrib/bmake/install-sh (revision af23369a6deaaeb612ab266eb88b8bb8d560c322)
1:
2# NAME:
3#	install.sh - portable version of install(1)
4#
5# SYNOPSIS:
6#	install [-CNcs] [-f flags] [-i errs] [-o owner] [-g group] [-m mode] file1 file2 ...
7#	install -d  [-i errs] [-o owner] [-g group] [-m mode] directory ...
8#
9# DESCRIPTION:
10#	Compatible with BSD install(1).  Except that '-c' is always
11#	true and we always move an already installed target aside as
12#	this is important on many systems.  Recent BSD install(1)
13#	versions have a '-b' option for this.
14#
15#
16# OPTIONS:
17#	-b	move previous target file aside (always true).
18#
19#	-B "suffix"
20#		use "suffix" instead of .old for saving existing target.
21#
22#	-c	copy rather than move the file into place (always true).
23#
24#	-C	compare.  Only install if target is missing or
25#		different.
26#
27#	-N	newer. Only install if target is missing or older.
28#
29#	-s	strip target
30#
31#	-o "owner"
32#		make target owned by "owner"
33#
34#	-g "group"
35#		make target group owned by "group"
36#
37#	-m "mode"
38#		set permissions to "mode"
39#
40#	-f "flags"
41#		Pass "flags" onto chflags(1)
42#
43#	-i "errs"
44#		Ignore errors from steps indicated by "errs" (``s,o,g,m'').
45#
46# BUGS:
47#	The '-i' option is to save your sanity when 'bsd.prog.mk'
48#	insists on haveing a '-o' "owner" option which is doomed to
49#	fail on many systems.  We ignore '-b', '-B' and '-c' options.
50#
51# AUTHOR:
52#	Simon J. Gerraty <sjg@crufty.net>
53#
54
55# RCSid:
56#	$Id: install-sh,v 1.22 2023/01/28 16:21:19 sjg Exp $
57#
58#	@(#) Copyright (c) 1993-2023 Simon J. Gerraty
59#
60#	This file is provided in the hope that it will
61#	be of use.  There is absolutely NO WARRANTY.
62#	Permission to copy, redistribute or otherwise
63#	use this file is hereby granted provided that
64#	the above copyright notice and this notice are
65#	left intact.
66#
67#	Please send copies of changes and bug-fixes to:
68#	sjg@crufty.net
69#
70
71set -- `getopt B:bpxCNcsdo:g:m:i:f: $*`
72
73Mydir=`dirname $0`
74[ -s $Mydir/.installrc ] && . $Mydir/.installrc
75
76owner=:
77group=:
78mode=:
79MODE=0
80strip=:
81mkdirs=
82compare=:
83newer=:
84chflags=:
85LS_1=
86CP_p=
87
88while :
89do
90	case "$1" in
91	--)	shift; break;;
92	-p)	CP_p=-p;;
93	-x)	set -x;;
94	-B)	OLD_EXT=$2; shift;;
95	-C)	compare=Different;;
96	-N)	newer=Newer;
97		# check if /bin/ls supports -1
98		'ls' -1 $0 > /dev/null 2>&1 && LS_1=1
99		;;
100	-o)	owner="${CHOWN:-chown} $2 "; shift;;
101	-g)	group="${CHGRP:-chgrp} $2 "; shift;;
102	-m)	MODE=$2 mode="${CHMOD:-chmod} $2 "; shift;;
103	-s)	strip=${STRIP:-strip};;
104	-d)	mkdirs="mkdir -p";;
105	-i)	ignore_err="$ignore_err$2"; shift;;
106	-f)	chflags="${CHFLAGS:-chflags} $2 "; shift;;
107	*)	break;;
108	esac
109	shift
110done
111
112Newer() {
113	n=`'ls' -t$LS_1 $* 2> /dev/null | head -1`
114	[ $1 = $n ]
115}
116
117Different() {
118	cmp -s $*
119	[ $? != 0 ]
120}
121
122Err() {
123	case "$ignore_err" in
124	*$1*)	;;
125	*)	exit 1;;
126	esac
127}
128
129Setem() {
130	# the order is important
131	if [ ! -d $1 ]; then
132		$strip $1 || Err s
133	fi
134	$group $1 || Err g
135	$owner $1 || Err o
136	$mode  $1 || Err m
137	$chflags $1 || Err f
138	return 0
139}
140
141# a bug in HP-UX's /bin/sh, means we need to re-set $*
142# after any calls to add_path()
143args="$*"
144
145add_path () {
146	test -d $1 || return
147	case ":$PATH:" in
148	*:$1:*) return;;
149	esac
150	PATH=$PATH:$1
151}
152
153add_path /sbin
154add_path /usr/sbin
155
156case "$owner" in
157:)	;;
158*)
159	add_path /etc
160	add_path /usr/etc
161	;;
162esac
163
164# restore saved $*
165set -- $args
166
167# make directories if needed
168# and ensure mode etc are as desired
169if [ "$mkdirs" ]; then
170	case "$MODE" in
171	[1-7]*)
172		# make sure umask is compatible
173		case "$MODE" in
174		????*) MODE=`echo $MODE | sed 's,.*\(...\)$,\1,'`;;
175		esac
176		umask `expr 0777 - 0$MODE |
177		sed 's,^,000,;s,^.*\(...\)$,\1,'`;;
178	esac
179	for d in $*
180	do
181		[ ! -d $d ] && $mkdirs $d
182		Setem $d
183	done
184	exit 0			# that's all we do
185fi
186
187# install files
188if [ $# -gt 2 ]; then
189	dest_dir=yes
190elif [ $# -eq 1 ]; then
191	echo "what should I do with $*?" >&2
192	exit 1
193fi
194
195# get list of files
196while [ $# -gt 1 ]
197do
198	files="$files $1"
199	shift
200done
201# last one is dest
202dest=$1
203shift
204
205
206if [ "$dest_dir" = yes -a  ! -d $dest ]; then
207	echo "no directory $dest" >&2
208	exit 1
209fi
210
211for f in $files
212do
213	b=`basename $f`
214	if [ -d $dest ]; then
215		t=$dest/$b
216	else
217		t=$dest
218	fi
219	$newer $f $t || continue
220	$compare $f $t || continue
221	[ -f $t ] && { mv -f $t $t.old || exit 1; }
222	{ cp $CP_p $f $t && Setem $t; } || exit 1
223done
224exit 0
225