#!/bin/sh
# OpenDarwin install script
# $Id: rc.cdrom,v 1.30 2005/04/28 20:06:46 kevin Exp $

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 () {
	
	# a few helper vars
	# make T_PW and T_PW_2 not equal
	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
}

# and a way to iterate through the list of available services
# with a method to initialize them
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
}

# This function will nuke the whole disk and create the 0xAB and 0xA8
# partitions.  $INSTALLDEV and $RAWINSTDEV need to be set to the
# device to nuke, and the corresponding raw device.
partition_disk () {
	# needs help on ppc
	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

}

# This will look for partitions on the selected disk, and 
# allow the user to select the 0xA8 partitions to use.
# $INSTALLDEV needs to be set to the device to look for,
# and $ROOTPART will be set to the chosen value upon return.
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"

}

# This just runs fdisk interactivly on the chosen raw install device
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

	# Get the device the user wants to install onto.
	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
				   	# Don't ask which to use, since we already know.
				   	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
				   	# Don't ask which to use, since we already know.
				   	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"
	
	# loop until password was entered the same twice
	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
}
	
# Set the erase character properly
# This is only for telnet consoles...
#stty erase 

# Ignore ^C
#trap "" 2

main

exit
