Home | History | Annotate | Line # | Download | only in dist
      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