#!/bin/sh
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/libexec:/etc:/private/etc ; export PATH
ARCH=`arch`
TARGET_MOUNT=/mnt
AVAIL_SHELLS="sh tcsh csh bash zsh"
T_UID_DEFAULT=1000
T_GID_DEFAULT=1000
abort () {
echo "Aborting the installation"
echo "Press enter to reboot"
read REBOOT
reboot
}
umount_target_disk () {
umount ${ROOTPART}
if [ "${ARCH}" == "ppc" ]; then
${PDISKCOMMAND}
fi
}
finishup () {
echo "Installation of the base system is now complete."
echo "You may: "
until [ ! : ]
do
echo "1) add a user to the new system"
echo "2) Reboot"
echo "3) Spawn a shell"
echo -n "Your Choice: "
read CHOICE
case ${CHOICE} in
1) add_user ;;
2) umount_target_disk
reboot
break ;;
3) umount_target_disk
/bin/sh
break ;;
esac
done
}
add_user () {
ADMIN_USER=0
SHELL_VALID=0
T_PW=0
T_PW_2=1
echo ""
echo -n "Username: "
read T_USERNAME
echo -n "Realname: "
read T_REALNAME
echo -n "UID (default: ${T_UID_DEFAULT}): "
read T_UID
echo -n "GID (default: ${T_GID_DEFAULT}): "
read T_GID
if [ "$T_UID" == "" ]; then
T_UID=${T_UID_DEFAULT}
fi
if [ "$T_GID" == "" ]; then
T_GID=${T_GID_DEFAULT}
fi
until [ "$SHELL_VALID" == "1" ]; do
echo -n "Available shells: "
for shell in ${AVAIL_SHELLS}
do
echo -n "${shell} "
done
echo ""
echo -n "Shell: "
read T_SHELL;
for shell in ${AVAIL_SHELLS}
do
if [ "$T_SHELL" == "$shell" ]; then
SHELL_VALID=1
fi
done
done
echo -n "Home directory (default: /Users/${T_USERNAME}): "
read T_HOMEDIR;
if [ "$T_HOMEDIR" == "" ]; then
T_HOMEDIR=/Users/${T_USERNAME}
fi
echo -n "Add ${T_USERNAME} to the admin group? (yes/no): "
read CHOICE;
if [ "$CHOICE" == "yes" ]; then
ADMIN_USER=1
fi
while [ 1 ]; do
T_PW=`openssl passwd`
if [ ${?} == "0" ]; then
break
fi
done
echo ""
echo "Username: ${T_USERNAME}"
echo "Realname: ${T_REALNAME}"
echo "UID: ${T_UID}"
echo "GID: ${T_GID}"
echo "Shell: ${T_SHELL}"
echo "Home: ${T_HOMEDIR}"
echo ""
echo -n "Add (yes/no): "
read CHOICE
if [ "$CHOICE" == "yes" ]; then
nicl -raw ${TARGET_MOUNT}/var/db/netinfo/local.nidb -create /users/${T_USERNAME} passwd ${T_PW}
nicl -raw ${TARGET_MOUNT}/var/db/netinfo/local.nidb -create /users/${T_USERNAME} realname ${REALNAME}
nicl -raw ${TARGET_MOUNT}/var/db/netinfo/local.nidb -create /users/${T_USERNAME} uid ${T_UID}
nicl -raw ${TARGET_MOUNT}/var/db/netinfo/local.nidb -create /users/${T_USERNAME} gid ${T_GID}
nicl -raw ${TARGET_MOUNT}/var/db/netinfo/local.nidb -create /users/${T_USERNAME} shell /bin/${T_SHELL}
nicl -raw ${TARGET_MOUNT}/var/db/netinfo/local.nidb -create /users/${T_USERNAME} home ${T_HOMEDIR}
nicl -raw ${TARGET_MOUNT}/var/db/netinfo/local.nidb -create /groups/${T_USERNAME} name ${T_USERNAME}
nicl -raw ${TARGET_MOUNT}/var/db/netinfo/local.nidb -create /groups/${T_USERNAME} gid ${T_GID}
nicl -raw ${TARGET_MOUNT}/var/db/netinfo/local.nidb -create /groups/${T_USERNAME} passwd "*"
if [ "$ADMIN_USER" == "1" ]; then
nicl -raw ${TARGET_MOUNT}/var/db/netinfo/local.nidb -create /groups/admin users ${T_USERNAME}
fi
mkdir -p ${TARGET_MOUNT}/${T_HOMEDIR}
chown ${T_UID}:${T_GID} ${TARGET_MOUNT}/${T_HOMEDIR}
echo "User ${T_USERNAME} created"
echo ""
if [ "$T_UID" == "$T_UID_DEFAULT" ]; then
T_UID_DEFAULT=$(($T_UID_DEFAULT+1))
T_GID_DEFAULT=$(($T_GID_DEFAULT+1))
fi
fi
}
enable_various_services() {
echo "Following services can be enabled: "
chroot ${TARGET_MOUNT} /sbin/service --list
while [ 1 ]; do
echo -n "Enter service to enabled ('quit' to abort, list to print list): "
read SERVICE
if [ "$SERVICE" == "quit" ]; then
break
fi
if [ "$SERVICE" == "list" ]; then
chroot ${TARGET_MOUNT} /sbin/service --list
else
echo "Enabling service: ${SERVICE}"
sed -e 's/disable.*=.*yes/disable = no/' < ${TARGET_MOUNT}/etc/xinetd.d/${SERVICE} > ${TARGET_MOUNT}/etc/xinetd.d/${SERVICE}.new
mv ${TARGET_MOUNT}/etc/xinetd.d/${SERVICE}.new ${TARGET_MOUNT}/etc/xinetd.d/${SERVICE}
fi
done
}
choose_filesystem_type () {
while [ 1 ]; do
echo "Choose the filesystem type from the following."
echo " hfs) HFS+ (journaled) filesystem"
echo " ufs) UFS filesystem"
echo -n "Filesystem type: "
read FILESYSTEMTYPE
if [ "$FILESYSTEMTYPE" == "hfs" -o "$FILESYSTEMTYPE" == "ufs"]; then
break
fi
done
}
partition_disk () {
echo "Partitioning disk ${INSTALLDEV} using filesystem type ${FILESYSTEMTYPE}"
echo "Warning: this will destroy all data on the disk!"
echo -n "Continue? (y/n) "
read CONT
if [ "${CONT}" == "y" -o "${CONT}" == "yes" ]; then
fdisk -i -y -a ${FILESYSTEMTYPE} ${RAWINSTDEV}
else
abort
fi
}
use_partitions () {
echo ""
PARTS=`ls -1 ${INSTALLDEV}s*`
echo "The following partitions are available:"
for devs in ${PARTS}
do
echo ${devs}
done
ROOTPART=""
until [[ ${ROOTPART} != "" && -b ${ROOTPART} ]]
do
echo "Which will be the root partition?"
read ROOTPART
done
echo "Using: "
echo "${ROOTPART} as the root partition"
}
run_fdisk () {
echo "Starting fdisk"
if [ "${ARCH}" == "i386" ]; then
fdisk -e ${RAWINSTDEV}
elif [ "${ARCH}" == "ppc" ]; then
/usr/sbin/pdisk
fi
}
install_booter () {
if [ "${ARCH}" == "i386" ]; then
cd /
umount -f ${ROOTPART}
RAWROOTPART=`echo ${ROOTPART} | sed 's/disk/rdisk/'`
if [ "${FILESYSTEMTYPE}" == "ufs" ]; then
dd if=/usr/standalone/i386/boot1u of=${RAWROOTPART} bs=512 count=15 >>/dev/null 2>&1
elif [ "${FILESYSTEMTYPE}" == "hfs" ]; then
dd if=/usr/standalone/i386/boot1h of=${RAWROOTPART} bs=512 count=1 >>/dev/null 2>&1
/usr/sbin/startupfiletool ${RAWROOTPART} /usr/standalone/i386/boot >/dev/null 2>&1
bless -device ${ROOTPART} -setBoot >/dev/null 2>&1
fi
mount -t ${FILESYSTEMTYPE} ${ROOTPART} ${TARGET_MOUNT}
bless -mount ${TARGET_MOUNT} -setBoot >/dev/null 2>&1
cd ${TARGET_MOUNT}
elif [ "${ARCH}" == "ppc" ]; then
PDISKCOMMAND=`bless -folder ${TARGET_MOUNT}/System/Library/CoreServices -folder9 ${TARGET_MOUNT}/System/Library/CoreServices -bootinfo ${TARGET_MOUNT}/usr/standalone/ppc/bootx.bootinfo -bootBlockFile ${TARGET_MOUNT}/usr/share/misc/bootblockdata -systemfile ${TARGET_MOUNT}/usr/share/misc/hdbootdata -xcoff ${TARGET_MOUNT}/usr/standalone/ppc/bootx.xcoff -label ${VOLUMENAME} -setOF`
fi
}
install_packages () {
VOLUMENAME="Darwin"
echo "WARNING: answering "yes" here will destroy all data on the partition"
until [ ! : ]
do
echo -n "Would you like to do a clean install? (yes/no)"
read ANSWER
if [ "$ANSWER" == "yes" ]; then
echo -n "Desired Volumename: "
read VOLUMENAME
echo "Creating ${FILESYSTEMTYPE} Filesystem on ${ROOTPART}"
if [ "${FILESYSTEMTYPE}" == "hfs" ]; then
newfs_hfs -J -v "${VOLUMENAME}" ${ROOTPART} >> /dev/null 2>&1
break
elif [ "${FILESYSTEMTYPE}" == "ufs" ]; then
newfs -v "${VOLUMENAME}" ${ROOTPART} >> /dev/null 2>&1
break
fi
elif [ "$ANSWER" == "no" ]; then
break
fi
done
mount -t ${FILESYSTEMTYPE} ${ROOTPART} ${TARGET_MOUNT}
cd ${TARGET_MOUNT}
echo "Installing packages on ${ROOTPART}"
for f in /System/Installation/Packages_${ARCH}/files-*.tar.bz2 \
/System/Installation/Packages_${ARCH}/*-*.tar.bz2 \
/System/Installation/BinaryDrivers_${ARCH}/*-*.tar.bz2 ; do
echo "Uncompressing $(basename $f)"
tar xjpf $f 2>/dev/null
done
cd /
}
main() {
if [ -f "/Release Notes.txt" ]; then
echo ""
echo "Welcome to the installation of" `grep 'Darwin [0-9.-]*' /Release\ Notes.txt | head -1 | awk '{print $1" "$2}'`
echo ""
fi
if [ -f "/Important Notice.txt" ]; then
cat "/Important Notice.txt"
fi
INSTALLDEV="novalue"
until [[ ${INSTALLDEV} != "" && -b ${INSTALLDEV} ]]
do
echo "The following devices are available for installation:"
until [[ ! -z "${FOO}" ]]
do
FOO=`iofindwholemedia`
done
iofindwholemedia
echo "Enter 'shell' to drop into a shell"
echo -n "Which device would you like to install Darwin onto? "
read INSTALLDEV
if [ "${INSTALLDEV}" == "shell" ]; then
exec /bin/sh
fi
INSTALLDEV=`iofindwholemedia ${INSTALLDEV}`
if [ ! -b "${INSTALLDEV}" ]; then
echo ""
echo "${INSTALLDEV} doesn't exist, please enter one of the listed devices."
echo ""
fi
done
RAWINSTDEV=`echo ${INSTALLDEV} | sed 's/disk/rdisk/'`
if [ "${ARCH}" == "i386" ]; then
if fdisk -t ${RAWINSTDEV} ; then
echo ""
echo "For partitioning the disk, you have the following choices:"
until [ ! : ]
do
echo "1) Auto-partition the disk (Destroys all disk contents)"
echo "2) Manually partition the disk using fdisk"
echo "3) Use existing partitions"
echo -n "Choice: "
read ANSWER
case ${ANSWER} in
1) choose_filesystem_type
partition_disk
ROOTPART="${INSTALLDEV}s1"
break
;;
2) run_fdisk
use_partitions
choose_filesystem_type
break
;;
3) use_partitions
choose_filesystem_type
break
;;
esac
done
else
echo ""
echo "For partitioning the disk, you have the following choices:"
until [ ! : ]
do
echo "1) Auto-partition the disk (Destroys all disk contents)"
echo "2) Manually partition the disk using fdisk"
echo -n "Choice: "
read ANSWER
case ${ANSWER} in
1) partition_disk
ROOTPART="${INSTALLDEV}s1"
break
;;
2) run_fdisk
use_partitions
break
;;
esac
done
fi
elif [ "${ARCH}" == "ppc" ]; then
until [ ! : ]
do
echo "Which partition would you like to install into: "
i=0
slice=`pdisk ${INSTALLDEV} -getPartitionOfType Apple_HFS $i 2> /dev/null`
if [ $? != 0 ]; then
echo "You have no partitions of type Apple_HFS! You really need at least one to install Darwin onto."
fi
until [[ $? != 0 ]]
do
name=`pdisk ${INSTALLDEV} -partitionName ${slice}`
echo "${i}) ${INSTALLDEV}s${slice} Apple_HFS ${name}"
i=`expr ${i} + 1`
slice=`pdisk ${INSTALLDEV} -getPartitionOfType Apple_HFS $i 2> /dev/null`
done
echo -n "Your choice: "
read ANSWER
slice=`pdisk ${INSTALLDEV} -getPartitionOfType Apple_HFS ${ANSWER}`
if [ -b "${INSTALLDEV}s${slice}" ]; then
ROOTPART="${INSTALLDEV}s${slice}"
break;
fi
done
fi
install_packages
install_booter
echo 'LANGUAGE=English' > ${TARGET_MOUNT}/var/log/CDIS.custom
echo "Updating mkext cache"
export TMPDIR=${TARGET_MOUNT}/private/tmp
kextcache -K ${TARGET_MOUNT}/mach_kernel -a ${ARCH} -m ${TARGET_MOUNT}/System/Library/Extensions.mkext ${TARGET_MOUNT}/System/Library/Extensions 2>/dev/null
export -n TMPDIR
echo "Creating root user"
while [ 1 ]; do
ROOT_PW=`openssl passwd`
if [ ${?} == "0" ]; then
break
fi
done
echo -n "Set computer name (Bonjour hostname): "
read BONJOUR
echo "$BONJOUR" | scutil --set ComputerName
echo "$BONJOUR" | tr A-Z a-z | sed -e 's/[^a-z0-9_-][^a-z0-9_-]*/-/g' | scutil --set LocalHostName
nicl -raw ${TARGET_MOUNT}/var/db/netinfo/local.nidb -create /users/root passwd ${ROOT_PW}
echo "Configuring emacs"
chroot ${TARGET_MOUNT} /usr/libexec/dumpemacs > /dev/null 2>&1
finishup
}
main
exit