#! /bin/bash
# vim:set sw=4 ts=4:
#! /bin/bash -x
#
##############################################################################
#
# $Id: make_inst_server,v 1.27 2005/04/11 14:14:34 fabian Exp $
#
##############################################################################
#
#
# NAME
#	make_inst_server - Create a directory hierarchy fitting the (Auto)YaST specifications
#
# SYNTAX
#   make_inst_server <options>
#
# DESCRIPTION
#	The "make_inst_server" script is used to create an installation server that
#	(Auto)YaST and ALICE (hereafter called AutoInstall) can make use of as source
#	for the products that are to be installed on the clients, where the AutoInstall
#	is being used.
#	This script creates the necessary directory structure the AutoInstall programs
#	need, and fills this directory structure with the product files specified at
#	call time, so that the server where this script was run, can be used as an
#	installation server for the AutoInstall programs.
#
#	One should be aware of that in order to create an installation server the path
#	into where the product files are installed, must be able to hold the data copied,
#	which can be a considerable amount of mega, if not giga, bytes!
#
#	The sources from where the products files are copied are usually from either CDs
#	or DVDs, but it can also be from other directories, where the product files are
#	already available.
#	This is usually the case, when the product files consist of customized packages.
#
# OPTIONS
#   -a <arch> 
#       Set the target architecture for InstallRoot (see -i).
#       Default is 'i386'.
#
#   -B        
#       make_inst_server will create the base/boot area in InstallRoot (see option '-i').
#       Default is off.
#
#   -b <path> 
#       Path to the base-area prio file (seufz).
#       This file contains the info to build the base-directory with the needed objects
#	(files and directories) from all given products.
#       For example SLES8 needs the "media.1", content from "SLES8", "boot/root" from
#	"SLES8", and "boot/loader" from "SP3".
#       So SLES8 has higher prio for "media.1", content and
#       The base-area is only built, if the -B option is used.
#
#       Default: The path defined in "/etc/sysconfig/alice" (ALICE_INSTBOOT_DSC).
#       If this sysconfig variable is NOT defined then make_inst_server uses file
#       "/usr/lib/alice2/dsc/instboot".
#
#   -c <prod>,<version>[,<prio1>,<prio2>[,<no>]]
#       Add product <prod> version <version> from a CD or DVD. This CD/DVD
#       must contain ONLY THIS SPECIFIC PRODUCT (not a multiple product media)
#       and the product must be in the ROOT DIRECTORY of the media.
#
#       The priorities are used to build the yast-Order files
#       <prio1>: "yast/order" <prio2>: "yast/instorder".
#       If two products have the same priority, the first one wins.
#       The <no> (default 0) is the number of the media to be copied.
#       If <no> is 0, then all media of the product are copied.
#
# TODO: -C Not implemented yet; use -p instead (CD/DVD already mounted)
#   -C <prod>,<version>[,<path>[,<prio1>,<prio2>[,<no>]]]
#       Add product <prod> version <version> from a CD or DVD. This CD/DVD
#       can contain MULTIPLE PRODUCTS.
#       The <path> is the relative path where to find the specific product on
#       the media.
#		
#       The priorities are used to build the yast-Order files
#       <prio1>: "yast/order" <prio2>: "yast/instorder".
#       If two products have the same priority, the first one wins.
#       The <no> (default 0) is the number of the media to be copied.
#       If <no> is 0, then all media of the product are copied.
#
#   -h	
#       Print a short help menu.
#
#   -i <path>
#       Change the default installation directory path name to <path>.
#       The default installation directory is "InstallRoot" in current directory.
#       If the directory does not exists, it will be created.
#
#   -n
#       Do not copy the media, only create links (-B) and add the product to the
#       yast order files.
#
#   -p <prod>,<version>[,<path>[,<prio1>,<prio2>[,<no>]]]
#       Add product <prod> version <version> found in the product source directory
#       (see option -s), or optionally from the passed relative <path> (relative
#       to the product source directory), to the installation root directory (see
#       option -i).
#       All other params: See option '-c'.
#       Option can be used multiple times in an accumulated manner to define
#       multiple products to be installed.
#       The <path> directory must exists, and must already comply with the
#       AutoInstall defined directory structure for products, i.e. having the
#       structure "<SourceDirectory>/<prod>/<version>/<arch>/{CD,DVD}[0-9]*",
#       or "<SourceDirectory>/<path>/CD*".
#
#   -s <path>
#       Change the global directory path <SourceDirectory> of where to find 
#       a product hierarchy of "<prod>/{CD,DVD}[0-9]*" to <path>.
#       The default directory path is "/suse/dists/SLES9".
#
# TODO: -v Not implemented yet
#   -v <level>
#       Set the verbosity to <level>.
#       Default level is 1, i.e. only very limited verbosity -- Use 0 for no verbosity.
#
# ARGUMENTS
#	None required nor accepted.
#
# FILES
#	None.
#
# SEE ALSO
#	bash(1),
#	AutoYaST(8), YaST(8)
#
# EXAMPLES
#	<Something useful to illustrate how this script works>
#
# AUTHOR
#	Created on 2004-Jun-25 by Fabian Herschel, SUSE LINUX AG <Fabian.Herschel@SUSE.com>
#
# RELEASED
#	make_inst_server - Create a directory hierarchy fitting the (Auto)YaST specifications
#
#	This program is released under the GPL Version 2 (or later), and is
#	Copyright (c) 2004 Fabian Herschel, SUSE LINUX AG <Fabian.Herschel@SUSE.com>
#	All rights reserved.
#
#	This program is free software; you can redistribute it and/or
#	modify it under the terms of the GNU General Public License
#	as published by the Free Software Foundation; either version 2
#	of the License, or (at your option) any later version.
#
#	This program is distributed in the hope that it will be useful,
#	but WITHOUT ANY WARRANTY; without even the implied warranty of
#	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#	GNU General Public License for more details.
#
#	You should have received a copy of the GNU General Public License
#	along with this program; if not, write to the Free Software
#	Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#
#	The creation of this script was sponsored in 2004 by
#	T-Mobile Deutschland GmbH, Bonn, Germany, EU.
#
# REVISION HISTORY
#	$Id: make_inst_server,v 1.27 2005/04/11 14:14:34 fabian Exp $
#
#	Use 'cvs log' to view the history log for this script.
# -------------------------------------------------------------------------------------------------
#
# TODO:
#		- -a sets InstArch but this is NOT used yet to test, wether the media are ok (matching)
#		- -C is not ready to use yet
#       - The boot(base) area is not created now
#
# -------------------------------------------------------------------------------------------------
# Initialization
 
set -o privileged		# Do not inherit functions.
set -o nounset			# Raise error on unset variable.
#set -o errexit			# Exit on first error.
set +o noglob			# Expand wildcards.
set +o noclobber		# Overwrite files.
set -o allexport		# Export all variables.
shopt -s expand_aliases		# Expand aliases, even if non interactive.
# set -o verbose		# List commands as they are read.
# set -o xtrace			# List commands after parameter expansion.
 
alias echo="echo -e"		# Allow the usage of escape sequences.

# Set our name:)
typeset -r PROG="${0##*/}"

# Default exit value
typeset -i _exit=0

# Where to create temporary working files
typeset -r TMP="/var/tmp/TMP-$$"


# -------------------------------------------------------------------------------------------------
# Default values for option changable values

# Default verbose level
typeset -i INFOlevel=1

# Initialize the product related variables:
#
# - ProductIndex is used an index pointer into the following arrays
# - ProductName array (-p,-c) contains the CD/DVD product name
# - ProductPath array (-p,-c) contains the alternative path where to find the product files
#
# In case a "ProductName" entry does not have an entry in either of "Product{CD,DVD}s", it
# means that the product sources are to be found relative to the "SourceDir" path, or alternatively
# relative to the path given by "ProductPath[${ProductIndex}]", if this has been set, under
# where a directory structure of "${ProductName[${ProductIndex}]}/{CD,DVD}[0-9]*" for the product
# files are expected to be found.  If not, this is an error.
declare -i  ProductIndex=0
declare -a  ProductName
#declare -ai ProductCDs
#declare -ai ProductDVDs
declare -a  ProductPath
declare -a  ProductMediaType

# Initialize the default values for the installation and source directories:
#
# - InstallDir (-i) contains the path to the directory where to create the install server dir
# - SourceDir (-s) containt the the path to the directory where to find the product files
declare InstallDir="./InstallRoot"
declare SourceDir="/suse/dists/SLES9"
declare CDrom="/dev/cdrom"
declare DescFile="/usr/lib/alice2/dsc/instboot"
declare CreateBootArea=0
declare InstArch="i386"
declare CopyTheMedia=1
declare ALICE_INSTBOOT_DSC=""
#
# read the alice sysconfig
#
if [[ -r /etc/sysconfig/alice ]]
then
	. /etc/sysconfig/alice
fi
if [[ -n "$ALICE_INSTBOOT_DSC" ]]
then
	DescFile="$ALICE_INSTBOOT_DSC"
fi
#
# -------------------------------------------------------------------------------------------------
# Function defintions

# Function to extract and print a nice self documenting help menu
function Usage()
{
    sed -e 's/^# \?//' -e '/^SYNTAX/,/^DESCRIPTION/!d' -e '/^DESCRIPTION/q' "${0}" | sed -e '$d'
    sed -e 's/^# \?//' -e '/^OPTIONS/,/^FILES/!d' -e '/^FILES/q' "${0}" | sed -e '$d'
    _exit 1
    # NEVER REACHED!
}

# Functions used to exit from script
function _exit()
{
    [[ -n "${1:-}" ]] && _exit=${1}
    # Ignore catching of script ending
    trap EXIT

    # Clean up after our selfs, if need be
    [[ -d "${TMP}" ]] && rm -rf "${TMP}"

    # Exit with set error code
    exit ${_exit}
    # NEVER REACHED!
}

trap _exit EXIT 1 2 3 15

function info()
{
    # set +o errexit			# Suspend: Exit on first error.
    local -i level=${1-0}
    shift
    if [[ ${INFOlevel} -ge ${level} ]]
    then
	if [[ $# -eq 0 ]]
	then
	    echo
	else
	    for text in "${@}"
	    do
		echo "${PROG}: ${text}"
	    done
	fi
    fi
    ## set -o errexit			# Restore: Exit on first error.
}

function error()
{
    # set +o errexit			# Suspend: Exit on first error.
    _exit=${1}
    shift
    if [[ "${1}" == "-c" ]]
    then
	continue=true
	shift
    fi
    for text in "${@}"
    do
	echo "${PROG}: ${text}"
    done

    if [[ -z "${continue:-}" ]]
    then
	_exit
	# NEVER REACHED!
    fi
}

# Function to set an integer value to a variable
#
#	setInteger <var> <value> [ <default value, if not 0> ]
function setInteger()
{
    declare var="${1}" value="${2}"
    declare -i defval="${3:-0}" result=0

    integer=$(expr match "${value}" '0*\([0-9]\+\)$')
    result=$?
	[[ ${result} -eq 1 && "${integer}" == "0" ]] && result=0
    [[ -z "${integer}" ]] && integer="${defval}"

    eval "${var}"="${integer}"
    return ${result}
}

# Check Media - Checks, if a media is the correct one
#
#
# FHBAUST
function CheckMedia()
{
	declare path="${1}" name="${2}" version="${3}" number="${4}"
	declare tmpProductName=""
	declare tmpProductVersion=""
	tmpProductName=$(awk '$1 == "PRODUCT" {for (i=2; i<NF; i++) {printf "%s ",$i}  printf "%s", $i}' $path/content)
	tmpProductVersion=$(awk '$1 == "VERSION" {print $2}' $path/content)
	if [[ ( "${tmpProductName}"    == "${name}" ) &&
		  ( "${tmpProductVersion}" == "${version}" )    ]]
	then
		if [ -r "${path}/media.${number}" ]
		then
			return 0 # everything is ok
		else
			return 1 # wrong media number
		fi
	else
		if [[ ( "${tmpProductName}" != "${name}"    ) ]]
		then
			return 4 # wrong product name
		else
			return 2 # wrong product version
		fi
	fi
	return 99
}

function PrintMediaValues()
{
	declare path="${1}"
	declare tmpProductName=""
	declare tmpProductVersion=""
	tmpProductName=$(awk '$1 == "PRODUCT" {for (i=2; i<NF; i++) {printf "%s ",$i}  printf "%s", $i}' $path/content)
	tmpProductVersion=$(awk '$1 == "VERSION" {print $2}' $path/content)
	tmpProductMediaNumber=$(cd ${path}; ls -d media.*)
	tmpProductMediaNumber=${tmpProductMediaNumber#media.}
	echo "The found media belongs to product $tmpProductName version $tmpProductVersion (media #$tmpProductMediaNumber)"
}

function MountMedia()
{
	declare tmpMountPoint
	case "$tmpMediaType" in
		CD )
			#   Let us guess that the correct device is /dev/cdrom
			#   if we want to change that, i guess we need an additional
			#   option for that.
			tmpMountPoint="/tmp/mnt.$$"
			# set +o errexit		# Suspend: Exit on first error.
			mkdir -p "$tmpMountPoint"
			mount $CDrom $tmpMountPoint
			echo $tmpMountPoint
			# set -o errexit		# Suspend: Exit on first error.
			;;
		DVD )
			# TODO: We need to import more than one
			# product from a DVD?
			;;
		DIR )
			# TODO:
			;;
	esac
}

function UMountMedia()
{
	declare tmpMountPoint
	case "$tmpMediaType" in
		CD )
			tmpMountPoint="/tmp/mnt.$$"
			set +o errexit		# Suspend: Exit on first error.
			umount $tmpMountPoint
			set -o errexit		# Suspend: Exit on first error.
			;;
		DVD )
			# TODO: We need to import more than one
			# product from a DVD?
			;;
		DIR )
			# TODO:
			;;
	esac
}

function ChangeMedia()
{
	declare cmMediaType="${1}"
	declare cmProductName="${2}"
	declare cmProductVersion="${3}"
	declare cmMediaNumber="${4}"
	case "$cmMediaType" in
		CD )
			echo -e "Please insert CD number $cmMediaNumber of $cmProductName V $cmProductVersion"
			read
			echo "Please wait..."
			;;
		DIR )
			;;
	esac
}

function CopyMedia()
{
	declare cmSrcPath="${1}"
	declare cmDestPath="${2}"
	mkdir -p "${cmDestPath}"
	( cd "${cmSrcPath}"; tar cf - . ) | ( cd "${cmDestPath}"; tar xf - )
}

function CreateBootArea()
{
	declare cbAMedia="${1}"
	declare cbADestPath="${2}"
	declare cbALine
	declare cbAdir
	echo
	echo "CREATE BOOT AREA OBJECTS"
	awk -F: '($1 == "link") && ($3 == media) { print $2} ' \
		media="$cbAMedia" < "${DescFile}" | while read cbALine
	do
		echo "- ${cbALine}"
	    if [[ "$(basename ${cbALine})" != "${cbALine}" ]]
		then	
			cbAdir="$(dirname ${cbALine})"
			(cd "${cbADestPath}"; mkdir -p "$(dirname ${cbALine})")
# TODO: Here only one dir level is solved by uplink, we need to count dir levels
#
			cbUp="../"
		else 
			cbAdir=""
			cbUp=""
		fi
		(cd "${cbADestPath}/${cbAdir}"; ln -sf "${cbUp}${cbAMedia}/${cbALine}")
	done
}

function split()
{
	declare tmpDelim="${1}"
	declare tmpList="${2}"
	declare tmpPos="${3}"
	declare tmpDef="${4}"
	tmpElem=$(echo "${tmpList}" | awk -F"${tmpDelim}" '{ printf "%s", $i} ' i="${tmpPos}" )
	if [[ -z "$tmpElem" ]]
	then
		tmpElem="${tmpDef}"
	fi
	echo "${tmpElem}"
}

function InsertInToFile()
{
	#
	# inserts a line into an existing file
	# the position gives the line AFTER the
	# given one have to be inserted.
	#
	# TODO:
	# any other lines, which are equal to the
	# line to be inserted are removed (so the
	# file has unique lines)
	#
	declare tmpFile="${1}"
	declare tmpLine="${2}"
	declare tmpPos="${3}"
	declare tmptmpFile=/tmp/file.$$	
	awk 'BEGIN     { inserted=0; } 
		NR == pos  { print $0; print lin; inserted=1 }
		NR != pos  { print $0; }
		END        { if (inserted==0) { print lin } } ' \
		pos="${tmpPos}" lin="${tmpLine}" "${tmpFile}" \
		> ${tmptmpFile}
	mv "${tmptmpFile}" "${tmpFile}"
}




# -------------------------------------------------------------------------------------------------
# Recognized options -- make use of "silent error" reporting from "getopts" (the first ":")!!
typeset -r OPTIONS="a:b:Bc:C:hi:np:s:v:"

# Decode the options
ArgMissing=""
while getopts "${OPTIONS}" opt
do
    case "${opt}" in
	a ) # Set the architecture
		#
		InstArch="${OPTARG}"
		;;
	B)  # Switch CreateBootArea 
		#  
		CreateBootArea=1
		;;
	b )	# Set path of the description file
		DescFile="${OPTARG}"
		;;

	c )	# Product CD/DVD (-C) with exactly ONE PRODUCT ON THE ROOT DIR
		# Product,Version[,prio1,prio2[,MediaNo]
		#
		# TODO: DVD is NOT supported now. You can use
		#       DVDs by mounting them and then use multiple -p options
		#
		# default: copy all CDs/DVDs the number of media is taken from
		# the media.1 file (of the first product CD)
		#
		#
		# if the prio is NOT supplied here, it is loaded from the 
		# description file (see -b)
		#
		# TODO: Change the docu of the optinal integer at other places in the script
	    tmpMediaType=CD
	    [[ "${opt}" == "C" ]] && tmpMediaType=DVD
		#
		#
		ProductName[${ProductIndex}]=$(split "," "${OPTARG}" 1 "NO-PRODUCT")
		ProductVersion[${ProductIndex}]=$(split "," "${OPTARG}" 2 "NO-VERSION")
		ProductPrio1[${ProductIndex}]=$(split "," "${OPTARG}" 3 -1)
		ProductPrio2[${ProductIndex}]=$(split "," "${OPTARG}" 4 -1)
		ProductMediaNumber[${ProductIndex}]=$(split "," "${OPTARG}" 5 0)
	    ProductMediaType[${ProductIndex}]="$tmpMediaType"
	    let ProductIndex+=1
	;;

	 C)	# Product CD/DVD (-C) with MORE THAN ONE PRODUCT
		# Product,Version[,path[,prio1,prio2[,MediaNo]]]
		#
		# TODO: DVD is NOT supported now. You can use
		#       DVDs by mounting them and then use multiple -p options
		#
		# default: copy all CDs/DVDs the number of media is taken from
		# the media.1 file (of the first product CD)
		# TODO: Change the docu of the optinal integer at other places in the script
	    tmpMediaType=CD
	    [[ "${opt}" == "C" ]] && tmpMediaType=DVD
		#
		#
		ProductName[${ProductIndex}]=$(split "," "${OPTARG}" 1 "NO-PRODUCT")
		ProductVersion[${ProductIndex}]=$(split "," "${OPTARG}" 2 "NO-VERSION")
		ProductPrio1[${ProductIndex}]=$(split "," "${OPTARG}" 3 1)
		ProductPrio2[${ProductIndex}]=$(split "," "${OPTARG}" 4 1)
		ProductMediaNumber[${ProductIndex}]=$(split "," "${OPTARG}" 5 0)
	    ProductMediaType[${ProductIndex}]="$tmpMediaType"
	    let ProductIndex+=1
	;;

	h)	# Print a short help menu.
	    Usage
	    # NEVER REACHED!
	;;

	i)	# Change the InstallDir path to where to create the install server files
	    InstallDir="${OPTARG}"
	;;

	n ) # Do not copy the media (only links and order)
		CopyTheMedia=0
	;;
	p)	# Product found relative to the SourceDir path (default see -s)
		ProductName[${ProductIndex}]=$(split "," "${OPTARG}" 1 "NO-PRODUCT")
		ProductVersion[${ProductIndex}]=$(split "," "${OPTARG}" 2 "NO-VERSION")
		tmpProdNVA="${ProductName[${ProductIndex}]}/${ProductVersion[${ProductIndex}]}/${InstArch}"
echo "### DBG $tmpProdNVA"
		ProductPath[${ProductIndex}]=$(split "," "${OPTARG}" 3 "$(echo ${tmpProdNVA} | tr ' ' '-' )")
		ProductPrio1[${ProductIndex}]=$(split "," "${OPTARG}" 4 -1)
		ProductPrio2[${ProductIndex}]=$(split "," "${OPTARG}" 5 -1)
		ProductMediaNumber[${ProductIndex}]=$(split "," "${OPTARG}" 6 0)
	    ProductMediaType[${ProductIndex}]="DIR"
	    let ProductIndex+=1
	;;

	s)	# Change the global SourceDir path for already available product files
	    SourceDir="${OPTARG}"
	    [[ ! -d "${SourceDir}" ]] &&
		error 3 -c "Option ${opt}: ${SourceDir} is not a directory."
	;;

	v)	# Change the verbosity
	    opt_v=true
	    setInteger INFOlevel "${OPTARG}" "${INFOlevel}" ||
		error 2 -c "Option ${opt}: Passed value '${OPTARG}' is not an integer."
	;;

	:)	# Option requiring argument is missing its argument
	    echo "${PROG}: Option '${OPTARG}' requires an argument!"
	    ArgMissing=true
	;;

	?)	# Unknown option found
	    echo "${PROG}: Option '${OPTARG}' is unknown -- Ignored!"
	;;
    esac
done
# Shift any options off the argument stack
shift $((${OPTIND} - 1))

# Complain, if an option is missing its parameter
[[ -n "${ArgMissing}" ]] && Usage

# Cannot continue, if an error was detected!
[[ ${_exit} -ne 0 ]] && exit

# Write protect the fetched values
typeset -r InstallDir SourceDir ProductIndex ProductName ProductCDs ProductDVDs ProductPath
typeset -r opt_v INFOlevel

# debug some arrays
#typeset -a -p

# -------------------------------------------------------------------------------------------------
# Decode arguments...

# None to decode and none expected!
[[ $# -gt 0 ]] && Usage

#
###########################
#
# create the master structure
#
mkdir -p ${InstallDir}/yast
touch ${InstallDir}/yast/order
touch ${InstallDir}/yast/instorder
#
## For each product list ...
#
declare -i PNumber
PNumber=${#ProductName[@]}
declare -i PCount=0
#
#### If boot/base creation is switched on, check if the dsc file is
#### available
#
if [[ "${CreateBootArea}" == 1 ]]
then
	if [[ ! -r "${DescFile}" ]]
	then
		echo "Description file ${DescFile} not readable"
		exit 1
	fi
fi
#
#### FOR-EACH-PRODUCT
####
#
while [ $PCount -lt $PNumber ]
do
	declare -i tmpProdPrio1
	declare -i tmpProdPrio2
	tmpMediaType="${ProductMediaType[$PCount]}"
	if [[ "${ProductMediaNumber[$PCount]}" == 0 ]]
	then
		tmpMediaNumber=1
		tmpCDSet=1
	else
		tmpMediaNumber=${ProductMediaNumber[$PCount]}
		tmpCDSet=0
	fi
	tmpProceed=1
	while [[ "$tmpProceed" -eq 1 ]]     # FOR-EACH MEDIA OF A PRODUCT
	do
		#
		#
		#
		case "${tmpMediaType}" in
			CD )
				tmpCheckMedia=99
				while [[ "$tmpCheckMedia" -ne 0 ]]  # LOOP TILL WE GET THE MEDIA
				do
					set +o errexit		# Suspend: Exit on first error.
					ChangeMedia "${ProductMediaType[$PCount]}" "${ProductName[$PCount]}" \
								"${ProductVersion[$PCount]}" $tmpMediaNumber # optional prompt
					tmpSrcPath=$(MountMedia)
					CheckMedia "${tmpSrcPath}" "${ProductName[$PCount]}" "${ProductVersion[$PCount]}" $tmpMediaNumber
					tmpCheckMedia=$?
					if [[ "$tmpCheckMedia" -ne 0 ]]
					then
						PrintMediaValues "$tmpSrcPath"
						UMountMedia "$tmpSrcPath"
						echo "The media is not correct."
						case "$tmpCheckMedia" in
							1 )	echo "Wrong media number - need number $tmpMediaNumber"	
								;;
							2 ) echo "Wrong product version - need product version ${ProductVersion[$PCount]}"
									;;
							4 ) echo "Wrong product - need product ${ProductName[$PCount]}"
							;;
						esac
					fi
					set -o errexit		# Restore: Exit on first error.
				done
				;;
			DIR )
				# TODO: - Maybe we also need to search DVDn
				#       - For now we only allow releative product paths (rel from SourceDir)
				#		- We can not guess the architecture - so we need an option for that
				#         In that case the source-structure can be:
				#         <SourceDir>/<product>/<version>/<architecture>/<media>n
				#
				tmpProductPath="${ProductPath[$PCount]}"
				# if [ -z "${tmpProductPath}" ]
				# then
				# 	tmpProductPath="${ProductPath[$PCount]}/${ProductPath[$PCount]}/###ARCHITECTURE###"
				# fi
				tmpSrcPath="${SourceDir}/${tmpProductPath}/CD${tmpMediaNumber}"
				CheckMedia "${tmpSrcPath}" "${ProductName[$PCount]}" "${ProductVersion[$PCount]}" $tmpMediaNumber
				tmpCheckMedia=$?
				if [[ "$tmpCheckMedia" -ne 0 ]]
				then
					PrintMediaValues "$tmpSrcPath"
					UMountMedia "$tmpSrcPath"
					echo "The media is not correct."
					case "$tmpCheckMedia" in
						1 )	echo "Wrong media number - need number $tmpMediaNumber"	
							;;
						2 ) echo "Wrong product version - need product version ${ProductVersion[$PCount]}"
								;;
						4 ) echo "Wrong product - need product ${ProductName[$PCount]}"
						;;
					esac
				fi
				;;
		esac
		#
		# we have successfully found the correct media :-)
		#
		# TODO:
		#       Is it allowed to have different DEFAULTBASEs for ONE
		#		InstallRoot?
		#
		tmpProductArch=$(awk '$1 == "DEFAULTBASE" {print $2}' $tmpSrcPath/content)
		ProductArch[$PCount]=$tmpProductArch   
		#
		#
		if [[ "$tmpMediaNumber" == 1 ]]
		then
			tmpMediaMaxCount=$(awk 'NR==3' $tmpSrcPath/media.1/media )
			tmpProductDirectory="${ProductName[$PCount]}/${ProductVersion[$PCount]}/${ProductArch[$PCount]}"
			tmpProductDirectory=$(echo "$tmpProductDirectory" | tr " " "-")
			ProductDirectory[$PCount]="$tmpProductDirectory"
			tmpP="/${tmpProductDirectory}/CD1"
			tmpPTabP=$(printf "%s\t%s" "${tmpP}" "${tmpP}")
			tmpProdPrio1="${ProductPrio1[$PCount]}"
			tmpProdPrio2="${ProductPrio2[$PCount]}"
			echo "---------------------------------------"
			echo "ProductName:       ${ProductName[$PCount]}"
			echo "ProductVersion:    ${ProductVersion[$PCount]}"
			echo "ProductDirectory:  ${ProductDirectory[$PCount]}"
			echo "ProductNoMedia:    ${tmpMediaMaxCount}"
			echo
			if [[ "$tmpProdPrio1" == -1 ]]
			then
				tmpProdPrio1=$(	
				    awk -F: '($1 == "prio1") && ($3 == product) { print $2} ' \
						product="$tmpProductDirectory" "${DescFile}"
							)
				echo "Using priority $tmpProdPrio1 for prio1 (defined in the description file)"
			fi
			if [[ "$tmpProdPrio2" == -1 ]]
			then
				tmpProdPrio2=$(	
				    awk -F: '($1 == "prio2") && ($3 == product) { print $2} ' \
						product="$tmpProductDirectory" "${DescFile}"
							)
				echo "Using priority $tmpProdPrio2 for prio2 (defined in the description file)"
			fi
			InsertInToFile "${InstallDir}/yast/order"     "${tmpPTabP}" "${tmpProdPrio1}"
			InsertInToFile "${InstallDir}/yast/instorder" "${tmpP}"     "${tmpProdPrio2}"
		fi
		#
		#   echo "### DBG: tmpProductArch" $tmpProductArch
		#
		if [[ "$CopyTheMedia" == 1 ]]
		then
			if [[ "$tmpCDSet" == 1 ]]
			then
				echo "NOW I COPY THE INSTALL MEDIA (${tmpMediaNumber}/${tmpMediaMaxCount}) -- PLEASE BE PATIENT"
			else
				echo "NOW I COPY THE INSTALL MEDIA (${tmpMediaNumber})-- PLEASE BE PATIENT"
			fi
			CopyMedia "$tmpSrcPath" "${InstallDir}/${ProductDirectory[$PCount]}/CD${tmpMediaNumber}"
		else
			echo "Skip copy (used option -n)"
		fi
		if [[ "$CreateBootArea" == 1 ]]
		then
			tmpProductString=$(echo "${ProductName[$PCount]}/${ProductVersion[$PCount]}/${InstArch}/CD${tmpMediaNumber}" | tr " " "-")
			CreateBootArea "${tmpProductString}" "${InstallDir}"
		fi
		#
		#
		UMountMedia "$tmpSrcPath"
		if [ "$tmpCDSet" -eq 0 ]
		then
			tmpProceed=0	# if we only have to copy a specific media, we can end here
		else
			if [[ ${tmpMediaNumber} -ge ${tmpMediaMaxCount} ]]
			then
				tmpProceed=0	# end after last media of the product
			else
				(( tmpMediaNumber++ ))
			fi
		fi
	done # loop for all media of a single product
	(( PCount++ ))
done

exit 99

# -------------------------------------------------------------------------------------------------
# Getting on with our business...

# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# From the release notes to SLES9:
#
#o Setting up an installation server for network installations
#
#	To set up an installation Server for installations via NFS/FTP/HTTP
#	the CDs have to be copied into a special directory structure.
#
#	Go to a directory of your choice and execute the following commands:
#
#	mkdir -p installroot/sles9/CD1
#	# now copy the contents of SLES CD1 into this directory
#	mkdir -p installroot/core9/CD1
#	# now copy the contents of SLES CD2 into this directory
#	mkdir -p installroot/core9/CD2
#	# now copy the contents of SLES CD3 into this directory
#	mkdir -p installroot/core9/CD3
#	# now copy the contents of SLES CD4 into this directory
#	mkdir -p installroot/core9/CD4
#	# now copy the contents of SLES CD5 into this directory
#	mkdir -p installroot/core9/CD5
#	# now copy the contents of SLES CD6 into this directory
#	ln -s sles9/CD1/boot boot
#	ln -s sles9/CD1/content content
#	ln -s sles9/CD1/control.xml control.xml
#	ln -s sles9/CD1/media.1 media.1
#	mkdir -p installroot/yast
#	echo "/sles9/CD1 /sles9/CD1\n/core9/CD1 /core9/CD1" > yast/instorder
#	echo "/sles9/CD1 /sles9/CD1\n/core9/CD1 /core9/CD1" > yast/order
#
#	If you are now asked for the installation directory just specify
#
#		installroot
#
#	If you want to set up a windows system as an install server go to
#	the directory dosutils/install. There is a script install.bat that
#	will create the structure and asks you for the CDs. There are also
#	to files instorder and order that have to be copied to the directory
#	\suseinstall\yast. Before you copy the order file please replace
#	the Variables UserAccount, PASSword and IP-Number with the respective
#	Values of your windows machine. During the installation process you
#	only need to specify the share suseinstall.
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
exit 120


# End-Of-Script
# -------------------------------------------------------------------------------------------------
