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