#!/bin/sh
#
# $Id: mkcdroot,v 1.18 2002/08/21 03:13:11 bsd Exp $
#
# Copyright 2001, 2002 Brian S. Dean <bsd@bsdhome.com>
# All Rights Reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY BRIAN S. DEAN ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BRIAN S. DEAN BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
# DAMAGE.
#
# Author : Brian Dean
# Date : 15 April, 2001
#
PROG=`basename $0`
CDROOT_LIBDIR=LIBDIR_VALUE
PAUSE=1
#--------------------------------------------------------------------
# Operational defaults
#--------------------------------------------------------------------
DEF_BASE=/scratch/cdroot/cdroot # Prefix to <NewRootPath>
DEF_SRCTREE=/usr/src # head of the source tree
DEF_DOWORLD=1 # perform an installworld
DEF_DOKERN=1 # perform a buildkernel installkernel
DEF_DOFDBOOT=1 # generate a 2.88 boot floppy image
DEF_DOETCSRC=1 # populate /etc from /usr/src ($SRCTREE)
DEF_DOETC=1 # populate /etc with new files
DEF_DOSRC=0 # populate /usr/src on the CD from the host system sources
DEF_DOOBJ=0 # copy /usr/obj from the host system
DEF_DOPORTS=0 # copy /usr/ports from the host system
DEF_DOINSTPORTS=0 # install standard ports
DEF_DOINSTPKGS=0 # install standard packages
DEF_KERNCONF=CDROOT # default kernel configuration file
DEF_BOOTOPTS="" # default options to pass to the kernel
DEF_PKGDIR=/scratch/pub/FreeBSD/ports/i386/packages-4-stable/Latest
DEF_PKGLIST="XFree86 pdksh ddup"
BASE=$DEF_BASE
SRCTREE=$DEF_SRCTREE
DOWORLD=$DEF_DOWORLD
DOKERN=$DEF_DOKERN
DOFDBOOT=$DEF_DOFDBOOT
DOETCSRC=$DEF_DOETCSRC
DOETC=$DEF_DOETC
DOSRC=$DEF_DOSRC
DOOBJ=$DEF_DOOBJ
DOPORTS=$DEF_DOPORTS
DOINSTPORTS=$DEF_DOINSTPORTS
DOINSTPKGS=$DEF_DOINSTPKGS
KERNCONF=$DEF_KERNCONF
BOOTOPTS=$DEF_BOOTOPTS
PKGDIR=${DEF_PKGDIR}
PKGLIST=${DEF_PKGLIST}
#--------------------------------------------------------------------
# Support Functions
#--------------------------------------------------------------------
# Print negated "true"/"false", useful for diplaying default settings
# for -no* options, i.e., -nosrc.
tf_neg () {
if [ "$1" -eq 1 ]; then
echo "false"
else
echo "true"
fi
}
# Print "yes"/"no", useful for diplaying default settings of 1/0 based
# flags
yn () {
if [ "$1" -eq 1 ]; then
echo "yes"
else
echo "no"
fi
}
# function for error checking
ckrc () {
rc=$?
if [ "$rc" -ne 0 ]; then
echo -n "$PROG: $1 failed, rc=$rc"
if [ "$2" = "exit" ]; then
echo "aborting";
exit 1;
fi
echo
fi
}
# install resolv.conf for name lookups; this is needed for installing
# ports, etc., in a chroot'd environment on $DESTDIR
neednamelookups () {
if [ ! -f $DESTDIR/etc/resolv.conf ]; then
if [ -f /etc/resolv.conf ]; then
cp /etc/resolv.conf $DESTDIR/etc/resolv.conf
fi
fi
}
# Create directories if they don't alread exist
domkdir () {
for dir in $*; do
if [ ! -d $dir ]; then
echo "mkdir $dir"
rm -f $dir
mkdir -p $dir
fi
done
}
# Attempt to install a requested port
installport () {
neednamelookups
while [ "$#" -ge 1 ]; do
DIR=$1; shift
while [ "$#" -ge 1 ]; do
PORT=$1; shift
echo "Installing $DIR/$PORT ..."
chroot $DESTDIR \
/bin/sh -c "unset DESTDIR; cd /usr/ports/$DIR/$PORT && make install"
done
done
}
doworld () {
# Perform an installworld targeting the new root
DESTDIR="$1"
echo "DOWORLD: DESTDIR=$DESTDIR"
cd $SRCTREE
mkdir ${DESTDIR}/dist
make installworld DESTDIR=$DESTDIR
}
dokern () {
# Build and install a kernel for the new root
DESTDIR="$1"
echo "DOKERN: DESTDIR=$DESTDIR"
(cd $SRCTREE &&
make buildkernel installkernel KERNCONF=${KERNCONF} \
DESTDIR=$DESTDIR)
}
dosrc () {
# populate ${DESTDIR}/usr/src from ${SRCTREE}
DESTDIR="$1"
echo "populate ${DESTDIR}/usr/src from ${SRCTREE}"
mkdir -p ${DESTDIR}/usr/src && (cd ${DESTDIR}/usr/src &&
cp -rpv ${SRCTREE}/. .)
}
doetcsrc() {
DESTDIR="$1"
echo "DOETCSRC: DESTDIR=$DESTDIR"
echo "Populate /etc"
(cd $SRCTREE/etc && make DESTDIR=$DESTDIR distrib-dirs &&
make DESTDIR=$DESTDIR distribution)
echo "Making devices"
chroot $DESTDIR /bin/sh -c "(cd /dev && sh MAKEDEV all ad0s1a da0s1a)"
echo "Remove /etc/rc.system"
if [ -f ${DESTDIR}/rc.system ]; then
rm ${DESTDIR}/etc/rc.system
fi
echo "Installing password files"
chroot $DESTDIR /bin/sh -c "pwd_mkdb -p /etc/master.passwd"
echo "Generating login capabilities database"
chroot $DESTDIR /bin/sh -c "/usr/bin/cap_mkdb /etc/login.conf"
echo "Creating aliases database"
chroot $DESTDIR /bin/sh -c "unset $DESTDIR; /usr/bin/newaliases"
echo "Create /etc/objformat"
echo "OBJFORMAT=elf" > $DESTDIR/etc/objformat
echo "Create /etc/fstab"
echo "" > $DESTDIR/etc/fstab
echo "Enable logins on /dev/ttyd0"
tfile=/tmp/ttys.$$
cat $DESTDIR/etc/ttys | sed 's+^ttyd0 "/usr/libexec/getty std.9600" dialup off secure+ttyd0 "/usr/libexec/getty std.9600" dialup on secure+g' > $tfile && cp $tfile $DESTDIR/etc/ttys
rm -f $tfile
echo "Enable hardware flow control by default on std.9600"
tfile=/tmp/gettytab.$$
cat $DESTDIR/etc/gettytab | sed 's+^ :np:sp#9600:$+ :np:sp#9600:hw:+g' > $tfile && cp $tfile $DESTDIR/etc/gettytab
rm -f $tfile
}
dofdboot () {
DESTDIR="$1"
echo "DOFDBOOT: DESTDIR=$DESTDIR"
echo "Generating 2.88 MB boot floppy image"
KERNELIMG=${DESTDIR}/kernel
umount /mnt > /dev/null 2>&1
vnconfig -u /dev/vn0 > /dev/null 2>&1
echo "Initialize boot floppy image"
dd if=/dev/zero of=${DESTDIR}/boot/boot.fd bs=1024 count=2880
vnconfig -s labels -c /dev/vn0 ${DESTDIR}/boot/boot.fd
disklabel -Brw /dev/vn0c minimum2
newfs -o space -T minimum2 /dev/vn0c
mount /dev/vn0c /mnt
echo "Copy kernel from ${KERNELIMG} to the boot floppy"
cp ${KERNELIMG} /tmp/kernel
gzip /tmp/kernel
cp /tmp/kernel.gz /mnt
rm /tmp/kernel.gz
mkdir /mnt/boot
mkdir /mnt/boot/defaults
echo "Copy boot1, boot2, and loader to boot floppy"
(cd ${DESTDIR}/boot && cp -p boot1 boot2 loader /mnt/boot)
echo "Create boot.config"
echo "-P" > /mnt/boot.config
echo "-P" > ${DESTDIR}/boot.config
echo "Create loader.rc"
cat <<EOF > /mnt/boot/loader.rc
echo "BSD CDROM ROOT IMAGE"
echo "LOADING KERNEL"
load /kernel
boot -C $BOOTOPTS
EOF
cat <<EOF > ${DESTDIR}/boot/loader.rc
echo "BSD NO-EMULATION CDROM ROOT IMAGE"
echo "LOADING KERNEL"
load /kernel
boot -C $BOOTOPTS
EOF
umount /mnt
}
installcvsup () {
DESTDIR="$1"
# Provide a cvsup supfile to keep /usr/ports up to date
if [ ! -f $DESTDIR/root/ports-supfile ]; then
echo "Install ports cvsup file"
cat <<_EOD_ > $DESTDIR/root/ports-supfile
# cvsup -g -L 2 ports-supfile
*default host=cvsup8.FreeBSD.org
*default base=/usr
*default prefix=/usr
*default release=cvs tag=.
*default delete use-rel-suffix
*default compress
ports-all
_EOD_
fi
# Fetch cvsup if it is not yet installed
if [ ! -f $DESTDIR/usr/local/bin/cvsup ]; then
echo "Install cvsup"
cd $DESTDIR/root && \
fetch ${CVSUPLOC}/${CVSUP} && \
chroot $DESTDIR /bin/sh -c "unset DESTDIR; cd /root && pkg_add -v ${CVSUP} && rm -f ${CVSUP}"
fi
}
updateports () {
DESTDIR="$1"
echo "Update /usr/ports"
if [ ! -f /usr/local/bin/cvsup ]; then
echo
echo "You must install the cvsup package first."
echo
exit 1
fi
neednamelookups
chroot $DESTDIR /bin/sh -c \
"unset DESTDIR; cd /root && cvsup -g -L 2 ports-supfile"
}
# Display usage information
printusage () {
cat <<EOF
Usage: $PROG <options>
Create a new read only root area starting at $DEF_BASE.
The following options are supported:
-base : Override the root install location
[default=$DEF_BASE]
-srctree : Override the location of the source tree
[default=$DEF_SRCTREE]
-noworld : do not perform an "installworld"
[default=`tf_neg $DEF_DOWORLD`]
-nokern : do not perform a "buildkernel installkernel"
[default=`tf_neg $DEF_DOKERN`]
-nofdboot : do not generate a 2.88 boot floppy
[default=`tf_neg $DEF_DOFDBOOT`]
-noetcsrc : do not populate /etc from $SRCTREE
[default=`tf_neg $DEF_DOETCSRC`]
-noetc : do not populate /etc with new files
[default=`tf_neg $DEF_DOETC`]
-nosrc : do not populate /usr/src from the host system
[default=`tf_neg $DEF_DOSRC`]
-noobj : do not populate /usr/obj from the host system
[default=`tf_neg $DEF_DOOBJ`]
-noports : do not populate /usr/ports from the host system
[default=`tf_neg $DEF_DOPORTS`]
-noinstports : do not attempt to install standard ports
[default=`tf_neg $DEF_DOINSTPORTS`]
-noinstpkgs : do not attempt to install standard packages
[default=`tf_neg $DEF_DOINSTPKGS`]
-pkgdir : directory where packages are located
[default=$DEF_PKGDIR]
-pkglist : set list of packages to install
[default=$DEF_PKGLIST]
-kernconf : override the default kernel config file for building/installing
[default=$DEF_KERNCONF]
-bootopts : override the default kernel options passed by the loader
[default=$DEF_BOOTOPTS]
-now : do not pause for 5 seconds before performing actions
EOF
}
#------------------------------------------------------------
# check for command line options
#------------------------------------------------------------
while [ "$#" -ne 0 ]; do
VAL=1
case $1 in
-no*)
VAL=0;
;;
esac
case $1 in
-base)
BASE="$2"
shift; shift
;;
-srctree)
SRCTREE="$2"
shift; shift
;;
-noworld|-world)
DOWORLD=$VAL
shift
;;
-nokern|-kern)
DOKERN=$VAL
shift
;;
-nofdboot|-fdboot)
DOFDBOOT=$VAL
shift
;;
-noetcsrc|-etcsrc)
DOETCSRC=$VAL
shift
;;
-noetc|-etc)
DOETC=$VAL
shift
;;
-nosrc|-src)
DOSRC=$VAL
shift
;;
-noobj|-obj)
DOOBJ=$VAL
shift
;;
-noports|-ports)
DOPORTS=$VAL
shift
;;
-noinstports|-instports)
DOINSTPORTS=$VAL
shift
;;
-noinstpkgs|-instpkgs)
DOINSTPKGS=$VAL
shift
;;
-pkgdir)
PKGDIR=$2
shift; shift
;;
-pkglist)
PKGLIST=$2
shift; shift
;;
-kernconf)
KERNCONF="$2"
shift; shift
;;
-bootopts)
BOOTOPTS="$2"
shift; shift
;;
-now)
PAUSE=0
shift
;;
*)
echo
echo "$PROG: unknown option \"$1\""
printusage
exit 1
;;
esac
done
if [ "$#" -ne 0 ]; then
printusage
exit 1
fi
if [ $DOINSTPKGS -eq 1 -a $DOINSTPORTS -eq 1 ]; then
cat <<EOF
You have selected to install applications from both ports and
packages. These installation options are incompatible. Applications
can be installed from either ports or packages, but not both.
EOF
exit 1
fi
if [ -z "${SRCTREE}" ]; then
echo
echo "$PROG: you must specify the top of your source tree (-srctree)"
echo
exit 1
fi
export DESTDIR=/$BASE
if [ ! -d $DESTDIR ]; then
echo
echo "$PROG: Root location \"${DESTDIR}\" does not exist"
echo "$PROG: Please create \"$DESTDIR \" and try again."
echo
exit 1
fi
DESTDIR=`echo $DESTDIR | sed 's+//+/+g'`
#----------------------------------------------------------------------
# Print out the current installation options and give the operator
# a chance to exit before we charge off and do something drastic
#----------------------------------------------------------------------
cat <<EOF
$PROG: Installation Options:
root area [-base] = $DESTDIR
source tree [-srctree] = $SRCTREE
perform basic install (installworld) [-world] = `yn $DOWORLD`
build and install a kernel [-kern] = `yn $DOKERN`
generate a boot floppy [-fdboot] = `yn $DOFDBOOT`
populate /etc from source [-etcsrc] = `yn $DOETCSRC`
populate /etc with new files [-etc] = `yn $DOETC`
install /usr/src [-src] = `yn $DOSRC`
install /usr/obj [-obj] = `yn $DOOBJ`
install /usr/ports [-ports] = `yn $DOPORTS`
install applications from ports [-instports] = `yn $DOINSTPORTS`
install applications from packages [-instpkgs] = `yn $DOINSTPKGS`
package list to install [-pkglist] = $PKGLIST
package directory [-pkgdir] = $PKGDIR
kernel config file [-kernconf] = $KERNCONF
kernel boot options [-bootopts] = $BOOTOPTS
EOF
if [ "$PAUSE" -ne 0 ]; then
timeout=5
while [ $timeout -ne 0 ]; do
printf "\r "
printf "\rProceeding in $timeout seconds, press <CTRL>-C to cancel "
sleep 1
timeout=`expr $timeout - 1`
done
echo
echo
fi
#----------------------------------------------------------------------
# Populate the most basic components of the OS if requested
#----------------------------------------------------------------------
if [ "$DOWORLD" -eq 1 ]; then
doworld ${DESTDIR}
ckrc world exit
fi
if [ "$DOKERN" -eq 1 ]; then
dokern ${DESTDIR}
ckrc kernel exit
fi
if [ "$DOETCSRC" -eq 1 ]; then
doetcsrc ${DESTDIR}
ckrc etcsrc exit
fi
if [ "$DOETC" -eq 1 ]; then
echo "Create /etc/rc.conf"
cat <<EOF > $DESTDIR/etc/rc.conf
# /etc/rc.conf
#
# Generated by $PROG, `date`
#
# The options below can be overridden by entries on a floppy disk.
# Create a ufs filesystem on a floppy disk, create an etc directory,
# and put overrides there. Files are copied from the floppy:/etc and
# replaces files here at boot time. If you override this file,
# /etc/rc.conf, you should not change the options immediately below.
moused_enable=YES
moused_type=ps/2
moused_port=/dev/psm0
root_rw_mount=NO # let /etc/rc know that root is ro
update_motd=NO # don't try to update /etc/motd
diskless_mount=/etc/cdroot_mount # custom disk mounting program
#
# ********** WARNING **********
#
# These next two options are dangerous and can result in the loss of
# data on either ad0 or da0. Use with EXTREME caution.
#
# If cdroot_uselocaldisk is set to YES, then the /etc/cdroot_mount
# program looks for either ad0 or da0. If one of these is found, then
# it will be used to hold swap, /var, /tmp, and /local.
#
# The disk is initialized from scratch if the first fdisk slice does
# not contain a valid FreeBSD label. If a label is present, the
# filesystems are fsck'd and used as is. You can force the disk to be
# re-initialized each time by specifying cdroot_force_diskinit=YES.
cdroot_uselocaldisk=NO # use a local disk for swap, /var, /tmp, /local
cdroot_force_diskinit=NO # alway re-initialize the local disk
EOF
echo "Make sure /etc/mail/local-host-names exists"
touch ${DESTDIR}/etc/mail/local-host-names
echo "Install /etc/cdroot_mount"
cp ${CDROOT_LIBDIR}/cdroot_mount ${DESTDIR}/etc
echo "Install /etc/cdroot_initdisk"
cp ${CDROOT_LIBDIR}/cdroot_initdisk ${DESTDIR}/etc
echo "Install /etc/inst"
cp ${CDROOT_LIBDIR}/cdroot_inst ${DESTDIR}/etc/inst
echo "Install /etc/rc.replacement"
if [ ! -f "${DESTDIR}/etc/rc.system" ]; then
cp -p ${DESTDIR}/etc/rc ${DESTDIR}/etc/rc.system
fi
cp ${CDROOT_LIBDIR}/rc.replacement ${DESTDIR}/etc/rc
echo "Stash a copy of /dev/MAKEDEV into /etc"
cp -p ${DESTDIR}/dev/MAKEDEV ${DESTDIR}/etc
echo "Create /etc/install/dists.dat and pkgs.dat"
if [ ! -d ${DESTDIR}/etc/install ]; then
mkdir ${DESTDIR}/etc/install
fi
if [ ! -f ${DESTDIR}/etc/install/dists.dat ]; then
cat <<EOF > ${DESTDIR}/etc/install/dists.dat
bin catpages compat22 compat3x compat4x crypto dict doc games info
manpages ports proflibs src
EOF
else
echo "${DESTDIR}/etc/install/dists.dat already present, not replaced"
fi
if [ ! -f ${DESTDIR}/etc/install/pkgs.dat ]; then
cat <<EOF > ${DESTDIR}/etc/install/pkgs.dat
XFree86-4.1.0_4
emacs-20.7
pdksh-5.2.14
EOF
else
echo "${DESTDIR}/etc/install/pkgs.dat already present, not replaced"
fi
fi
if [ ! -f ${DESTDIR}/usr/hosts.db -a -f /usr/hosts.db ]; then
echo "install /usr/hosts.db"
cp -p /usr/hosts.db ${DESTDIR}/usr/hosts.db
fi
if [ "$DOFDBOOT" -eq 1 ]; then
dofdboot ${DESTDIR}
ckrc fdboot exit
fi
if [ "$DOSRC" -eq 1 ]; then
dosrc ${DESTDIR}
ckrc "populate ${DESTDIR}/usr/src from $SRCTREE" exit
fi
#----------------------------------------------------------------------
# Several following commands depend on the current working directory
# being the new root area
#----------------------------------------------------------------------
cd $DESTDIR || exit 1
# Create needed directories relative to the new root
domkdir local usr/local usr/local/etc/rc.d
#----------------------------------------------------------------------
# Install requested packages
#----------------------------------------------------------------------
if [ $DOINSTPKGS -eq 1 ]; then
echo "Copying packages to the chroot'd area ..."
if [ ! -d "${DESTDIR}/tmp/pkgs" ]; then
mkdir ${DESTDIR}/tmp/pkgs
ckrc "create temporary package directory" exit
fi
cp -p $PKGDIR/* ${DESTDIR}/tmp/pkgs
ckrc "copy packages to temporary package directory" exit
for PKG in $PKGLIST; do
echo "Installing package $PKG ..."
chroot ${DESTDIR} /bin/sh -c "unset DESTDIR; \
pkg_add -v /tmp/pkgs/$PKG.tgz"
done
rm -rf ${DESTDIR}/tmp/pkgs
ckrc "removal of temporary package directory"
fi
#----------------------------------------------------------------------
# Update /usr/ports if requested to do so
#----------------------------------------------------------------------
if [ "$DOPORTS" -eq 1 ]; then
updateports ${DESTDIR}
fi
#----------------------------------------------------------------------
# Try and provide a working /bin/ksh
#----------------------------------------------------------------------
if [ -d "${DESTDIR}/usr/ports/shells/pdksh" -a ! -f /bin/ksh ]; then
installport shells pdksh
fi
if [ ! -f ${DESTDIR}/bin/ksh ]; then
if [ -f "${DESTDIR}/usr/local/bin/ksh" ]; then
cp -p ${DESTDIR}/usr/local/bin/ksh ${DESTDIR}/bin/ksh
elif [ -f /usr/local/bin/ksh ]; then
cp -p /usr/local/bin/ksh ${DESTDIR}/bin/ksh
elif [ -f /bin/ksh ]; then
cp -p /bin/ksh ${DESTDIR}/bin/ksh
fi
fi
if [ -f ${DESTDIR}/bin/ksh ]; then
grep '^/bin/ksh' ${DESTDIR}/etc/shells > /dev/null 2>&1
rc=$?
if [ "$rc" -ne 0 ]; then
echo "/bin/ksh" >> ${DESTDIR}/etc/shells
fi
fi
#----------------------------------------------------------------------
# Attempt to install the standard ports if requested
#----------------------------------------------------------------------
if [ $DOINSTPORTS -eq 1 ]; then
# ports that require X11
installport x11 XFree86
installport editors emacs20
installport graphics xv
installport net ethereal
# Non-X11 ports
installport mail mutt procmail
installport net cvsup
installport security sudo
installport shells pdksh
installport sysutils lsof
fi
syntax highlighted by Code2HTML, v. 0.9.1