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