<?xml version="1.0" encoding="ISO-8859-1" ?><!-- -*- xml -*- -->

<appendix id="appendix-functions">
<title>functions</title>
<programlisting><![CDATA[#!/static/sh
#
# Metadistros boot up script - functions file
#
# Copyright 2003 Metadistros [ http://metadistros.hispalinux.es/ ]
# Distributed under the GPL

# Load configuration and i18n files
. /etc/metadistros/var.conf
. /etc/metadistros/i18n.conf


# ------------------------------------------------------------------------------ #
# Create new user, defined in /etc/metadistros/var.conf

createuser()
{
	echo "${USERNAME}::1000:${USERNAME}"    >> /etc/group
	echo "${USERNAME}:*:1000:1000:${HOSTNAME} User:/home/${USERNAME}:/bin/bash" >> /etc/passwd
	echo "${USERNAME}:*:11312:0:99999:7:::" >> /etc/shadow
}

# ------------------------------------------------------------------------------ #
# Usage: mountit src dst "options"

mountit()
{
	BUILTIN_FS="iso9660 ext2 vfat"
	if [ "${DEBUG}" = "yes" ]
	then
		for fs in ${BUILTIN_FS}; do
			test -b $1 && mount -t $fs $3 $1 $2 && return 0
		done
	else
		for fs in ${BUILTIN_FS}; do
			test -b $1 && mount -t $fs $3 $1 $2 >/dev/null 2>&1 && return 0
		done
	fi
	return 1
}

# ------------------------------------------------------------------------------ #
# Mount module disk

mountmodules()
{
	[ "${VERBOSE}" = "yes" ] && echo -n "${FMESSAGE1}"
	read a
	[ "${VERBOSE}" = "yes" ] && echo -n "${FMESSAGE2}"

	# Mount over /modules/others/
	if mountit /dev/fd0 /modules/others "-o ro"; then
		[ "${VERBOSE}" = "yes" ] && echo "${GREEN}OK.${NORMAL}"
		return 0
	fi
	[ "${VERBOSE}" = "yes" ] && echo "${FMESSAGE3}"
	return 1
}

# ------------------------------------------------------------------------------ #
# Unmount module disk

umountmodules()
{
	[ "${VERBOSE}" = "yes" ] && echo -n "${FMESSAGE4}"
	if [ "${DEBUG}" = "yes" ]
	then
		umount /modules/others
	else
		umount /modules/others 2>/dev/null
	fi
	[ "${VERBOSE}" = "yes" ] && echo "${DONEGREEN}"
}

# ------------------------------------------------------------------------------ #
# Ask user for modules

askmodules()
{
	MODULES="" # Reset variable
	TYPE="$1"; shift
	echo "${BLUE}${FMESSAGE5A} [ ${TYPE} ] ${FMESSAGE5B}"
	c=""; for m in "$@"; do
		if test -f "/modules/${TYPE}/$m"; then
			test -z "$c"  && { echo -n "    $m"; c="1"; } || { echo "               $m"; c=""; }
		fi
	done
	test -n "$c"  && echo ""
	echo "${FMESSAGE6A} [ ${TYPE} ] ${FMESSAGE6B}"
	echo "${FMESSAGE6C}"
	echo -n "${FMESSAGE7}"
	read MODULES
	case "${MODULES}" in
		n|N)
			MODULES="";
			;;
		y|"")
			MODULES="$*";
			;;
	esac
}

# ------------------------------------------------------------------------------ #
# Try to load the given modules (full path or current directory)

loadmodules()
{
	TYPE="$1"; shift
	[ "${VERBOSE}"     = "yes" ] && echo "0" > /proc/sys/kernel/printk
	[ "${DEBUG}"       = "yes" ] && echo "6" > /proc/sys/kernel/printk
	for i in "$@"; do
		[ "${VERBOSE}" = "yes" ] && echo -n "${FMESSAGE8} ${TYPE}... ${MAGENTA}${i}${NORMAL}"
		if test -f /modules/${TYPE}/$i && insmod -f /modules/${TYPE}/$i >/dev/null 2>&1
		then
			[ "${VERBOSE}" = "yes" ] && echo "${FMESSAGE9A} ${TYPE} ${FMESSAGE9B} \
				${MAGENTA}${i}${GREEN}.${NORMAL}"
			case "$TYPE" in
				scsi|SCSI)
					FOUND_SCSI="yes";
					;;
			esac
		fi
	done
	[ "${VERBOSE}"        = "yes" ] && echo -n "${CRE}"
	if [ "${FOUND_SCSI}"  = "yes" ]; then
		return 0
	else
		return 1
	fi
}

# ------------------------------------------------------------------------------ #
# Find /META directory in $DEVICES (CDROMs, HDs, etc.)

checkformetadirectory()
{
	FOUND_SCSI="$1"; shift

	# Check for ide-scsi supported CD-Roms et al.
	test -f /proc/scsi/scsi && FOUND_SCSI="yes"
	
	# Control kernel messages
	if [ "${DEBUG}" = "yes" ]
	then
		echo "6" > /proc/sys/kernel/printk
	else
		echo "0" > /proc/sys/kernel/printk
	fi	

	# Now that the right SCSI driver is (hopefully) loaded, try to find CDROM
	DEVICES="/dev/hd?"
	[ "${FOUND_SCSI}" = "yes" ] && DEVICES="/dev/scd? /dev/scd?? ${DEVICES}"
	# New: Also try parallel port CD-Roms [for Mike].
	DEVICES="${DEVICES} /dev/pcd?"

	test -n "${FOUND_SCSI}" && DEVICES="${DEVICES} /dev/sd?[1-9] /dev/sd?[1-9][0-9]"
	DEVICES="${DEVICES} /dev/hd?[1-9] /dev/hd?[1-9][0-9]"
	for i in ${DEVICES}
	do
		[ "${VERBOSE}" = "yes" ] && echo -n "${FMESSAGE10} ${MAGENTA}${i}${NORMAL}   "
		if mountit $i /cdrom "-o ro";
		then
			if test -d /cdrom/META
			then
				# Found META directory in $i DEVICE, break loop and return $i
				[ "${VERBOSE}" = "yes" ] && echo -n "${FMESSAGE11} \
					${MAGENTA}${i}${GREEN}...${NORMAL}"
				# Found META
				return 0
				break
			fi
			if [ "${DEBUG}" = "yes" ]
			then
				umount /cdrom
			else
				umount /cdrom >/dev/null 2>&1
			fi
		fi
	done

	# Not found META
	return 1
}

# ------------------------------------------------------------------------------ #
# Check for sufficient memory to mount extra ramdisk for /home + /var

checkformemory()
{

	# New in Kernel 2.4.x: tempfs with variable ramdisk size.
	# We check for available memory anyways and limit the ramdisks
	# to a reasonable size.
	#
	# Busybox don't have awk...
	#
	# FOUNDMEM="`awk '/MemTotal/{print $2}' /proc/meminfo`"
	# TOTALMEM="`awk 'BEGIN{m=0};/MemFree|Cached/{m+=$2};END{print m}' /proc/meminfo`"

	count="0"

	# Find available RAM memory
	for mem in `cat /proc/meminfo |grep "MemTotal:"`
	do
		count="`expr ${count} \+ 1`"
		[ "${count}" = "2" ] && FOUNDMEM="${mem}"
	done

	count="0" # Reset count
	
	# Find Free RAM memory
	for mem in `cat /proc/meminfo |grep "Cached:"`
	do
		count="`expr ${count} \+ 1`"
		[ "${count}" = "2" ] && cached="${mem}"
	done

	count="0" # Reset count

	for mem in `cat /proc/meminfo |grep "MemFree:"`
	do
		count="`expr ${count} \+ 1`"
		[ "${count}" = "2" ] && memfree="${mem}"
	done

	TOTALMEN="`expr ${cached} \+ ${memfree}`"

	# Be verbose if defined
	[ "${VERBOSE}" = "yes" ] && echo "${FMESSAGE12} ${YELLOW}${FOUNDMEM}${BLUE} ${NORMAL}"

	# Now we need to use a little intuition for finding a ramdisk size
	# that keeps us from running out of space, but still doesn't crash the
	# machine due to lack of Ram

	# Minimum size of additional ram partitions
	MINSIZE="2000"
	# At least this much memory minus 30% should remain when home and var are full.
	MINLEFT="16000"
	# Maximum ramdisk size
	MAXSIZE="`expr ${TOTALMEN} \- ${MINLEFT}`"
	# Default ramdisk size for ramdisk
	RAMSIZE="`expr ${TOTALMEN} \/ 5`"

	if test -n "${TOTALMEN}" -a "${TOTALMEN}" -gt "${MINLEFT}"
	then
		test -z "${RAMSIZE}" && RAMSIZE=1000000
		mkdir -p /ramdisk
		# tmpfs/varsize version, can use swap
		RAMSIZE="`expr $RAMSIZE \* 4`"
		[ "${VERBOSE}" = "yes" ] && echo -n "${FMESSAGE13A}${RAMSIZE}${FMESSAGE13B}"
		# We need /bin/mount here for the -o size= option (busybox don't have...this option :-(  )
		# /static/mount -t tmpfs -o "size=${RAMSIZE}k" /dev/shm /ramdisk && mkdir -p \
		# /ramdisk/home /ramdisk/var /ramdisk/dev /ramdisk/mnt && ln -s /ramdisk/home /ramdisk/var /
		if [ "${DEBUG}" = "yes" ]
		then
			/static/mount -t tmpfs /dev/shm /ramdisk && mkdir -p /ramdisk/home \
			/ramdisk/var /ramdisk/dev /ramdisk/mnt && ln -s /ramdisk/home /ramdisk/var /
		else
			/static/mount -t tmpfs /dev/shm /ramdisk >/dev/null 2>&1 && mkdir -p \
			/ramdisk/home /ramdisk/var /ramdisk/dev /ramdisk/mnt && ln -s \
			/ramdisk/home /ramdisk/var /
		fi

		if [ ! -e /ramdisk/dev/.devfsd ]
		then
			#mount devfs
			if [ "${DEBUG}" = "yes" ]
			then
				mount -t devfs devfs /ramdisk/dev
			else
				mount -t devfs devfs /ramdisk/dev >/dev/null 2>&1
			fi
		fi

		[ "${VERBOSE}" = "yes" ] && echo "${DONEBLUE}"
	else
		mkdir -p /home /var
	fi

}

# ------------------------------------------------------------------------------ #
# Mount (c)loop image

mountimage()
{
	if test "${FOUND_META}" != "no" -a -f /cdrom/META/${DISTRO}.cloop; then
		# Found compressed image (cloop)
		
		if [ "${DEBUG}" = "yes" ]
		then
			mknod /dev/cloop b 240 0
		else
			mknod /dev/cloop b 240 0 >/dev/null 2>/dev/null
		fi
		if [ "$CDCACHE" = "yes" ]
		then
			[ "${VERBOSE}" = "yes" ] && echo -e "${FMESSAGE14}"
			cp /cdrom/META/${DISTRO}.cloop /ramdisk/mnt/
			if [ $? -ne 0 ]
			then
				[ "${VERBOSE}" = "yes" ] && echo -e "${FMESSAGE15}"
				CDCACHE="no"
				rm -f /ramdisk/mnt/${DISTRO}.cloop
			else
				if [ "${DEBUG}" = "yes" ]
				then
					insmod -f /modules/cloop.o file=/cdrom/META/${DISTRO}.cloop
				else
					insmod -f /modules/cloop.o file=/cdrom/META/${DISTRO}.cloop \
					>/dev/null 2>&1
				fi
				mountit /dev/cloop /META "-o ro" || FOUND_META="no"
			fi
		fi
		if [ "$CDCACHE" = "no" ]
		then
			[ "${VERBOSE}" = "yes" ] && echo -e "${FMESSAGE16}"

			if [ "${DEBUG}" = "yes" ]
			then
				insmod -f /modules/cloop.o file=/cdrom/META/${DISTRO}.cloop
			else
				insmod -f /modules/cloop.o file=/cdrom/META/${DISTRO}.cloop >/dev/null 2>&1
			fi
			mountit /dev/cloop /META "-o ro" || FOUND_META="no"
		fi
	fi

	if test "${FOUND_META}" != "no" -a -f /cdrom/META/${DISTRO}.loop; then
		# Found loop image
		
		if [ "${DEBUG}" = "yes" ]
		then
			mknod /dev/loop0 b 7 0
		else
			mknod /dev/loop0 b 7 0 >/dev/null 2>/dev/null
		fi
		[ "${VERBOSE}" = "yes" ] && echo -e "${FMESSAGE17}"
		losetup /dev/loop0 /cdrom/META/${DISTRO}.loop
		mountit /dev/loop0 /META "-o ro" || FOUND_META="no"
	fi
}

# ------------------------------------------------------------------------------ #
# Create common WRITABLE (empty) dirs

createdirs()
{
	[ "${VERBOSE}" = "yes" ] && echo -n "${FMESSAGE18}"

	# A metadistro don't will have all the files/directories list below

	# Show debug info?
	if [ "${DEBUG}" = "yes" ]
	then
		# Create common WRITABLE (empty) dirs
		/bin/mkdir -p /var/run /var/backups /var/cache/apache /var/local /var/lock/news \
			/var/nis /var/preserve /var/state/misc /var/tmp /var/lib \
			/var/spool/cups/tmp \
			/mnt/cdrom /mnt/floppy /mnt/hd /mnt/test \
			/home/${USERNAME} /root /etc/metadistros /etc/X11 /etc/cups
		/bin/chown ${USERNAME}.${USERNAME} /home/${USERNAME}
		# Create empty utmp and wtmp
		:> /var/run/utmp
		:> /var/run/wtmp
		# CUPS wants writable files. :-/ 
		 /bin/cp -a /META/etc/cups/*.conf /etc/cups/
		# All files in here should be size zero after Knoppix.clean was run
		/bin/cp -a /META/var/local /META/var/games /META/var/log \
			/META/var/spool /var/
		/bin/cp -a /META/var/lib/games /META/var/lib/wine \
			/META/var/lib/nfs /META/var/lib/xkb /META/var/lib/isdn \
			/META/var/lib/kdm /META/var/lib/pcmcia \
			/META/var/lib/dhcp* \
			/var/lib/
		# Problematic directories in /var/lib (lots and lots of inodes)
		/bin/ln -s /META/var/lib/dpkg /META/var/lib/apt /META/var/lib/doc-base \
			/META/var/lib/gnome /META/var/lib/kde \
			/META/var/lib/scrollkeeper /META/var/lib/texmf \
			/var/lib/
		# Debian-apt
		/bin/ln -s /META/var/cache/apt /var/cache/
		/bin/ln -s /META/etc/skel /META/etc/nessus /etc/dhcpc/resolv.conf \
			/etc/ 
		/bin/ln -s /META/dev/* /dev/
		# Index files can be HUGE, so better replace cache/man tree by links later
		# cp -a /META/var/cache/man /var/cache/ [ "${DEBUG}" = "no" ] && 2>/dev/null
		# Create links from CDROM for UNWRITABLE (remaining) files
		/bin/cp -aus /META/var/* /var/
		/bin/cp -aus /META/etc/* /etc/
		# Make SURE that these are files, not links!
		/bin/rm -rf /etc/ftpusers /etc/passwd /etc/shadow /etc/group \
			/etc/ppp /etc/isdn /etc/ssh /etc/ioctl.save \
			/etc/inittab /etc/network /etc/sudoers \
			/etc/init /etc/localtime /etc/dhcpc /etc/pnm2ppa.conf
		/bin/cp -a /etc/ftpusers /META/etc/passwd /META/etc/shadow /META/etc/group \
			/META/etc/ppp /META/etc/isdn /META/etc/ssh \
			/META/etc/inittab /META/etc/network /META/etc/sudoers \
			/META/sbin/init /META/etc/dhcpc /etc/
		# Extremely important, init crashes on shutdown if this is only a link
		:> /etc/ioctl.save
		:> /etc/pnm2ppa.conf
		# Diet libc bug workaround
		/bin/cp -f /META/etc/localtime /etc/localtime

	else
		# Create common WRITABLE (empty) dirs
		/bin/mkdir -p /var/run /var/backups /var/cache/apache /var/local /var/lock/news \
			/var/nis /var/preserve /var/state/misc /var/tmp /var/lib \
			/var/spool/cups/tmp \
			/mnt/cdrom /mnt/floppy /mnt/hd /mnt/test \
			/home/${USERNAME} /root /etc/metadistros /etc/X11 /etc/cups >/dev/null 2>&1
		/bin/chown ${USERNAME}.${USERNAME} /home/${USERNAME} >/dev/null 2>&1
		# Create empty utmp and wtmp
		:> /var/run/utmp >/dev/null 2>&1
		:> /var/run/wtmp >/dev/null 2>&1
		# CUPS wants writable files. :-/
		/bin/cp -a /META/etc/cups/*.conf /etc/cups/ >/dev/null 2>&1 
		# All files in here should be size zero after Knoppix.clean was run
		/bin/cp -a /META/var/local /META/var/games /META/var/log \
			/META/var/spool /var/ >/dev/null 2>&1
		/bin/cp -a /META/var/lib/games /META/var/lib/wine \
			/META/var/lib/nfs /META/var/lib/xkb /META/var/lib/isdn \
			/META/var/lib/kdm /META/var/lib/pcmcia \
			/META/var/lib/dhcp* \
			/var/lib/ >/dev/null 2>&1
		# Problematic directories in /var/lib (lots and lots of inodes)
		/bin/ln -s /META/var/lib/dpkg /META/var/lib/apt /META/var/lib/doc-base \
			/META/var/lib/gnome /META/var/lib/kde \
			/META/var/lib/scrollkeeper /META/var/lib/texmf \
			/var/lib/ >/dev/null 2>&1
		# Debian-apt
		/bin/ln -s /META/var/cache/apt /var/cache/ >/dev/null 2>&1
		/bin/ln -s /META/etc/skel /META/etc/nessus /etc/dhcpc/resolv.conf \
			/etc/ >/dev/null 2>&1
		/bin/ln -s /META/dev/* /dev/ >/dev/null 2>&1
		# Index files can be HUGE, so better replace cache/man tree by links later
		# cp -a /META/var/cache/man /var/cache/ [ "${DEBUG}" = "no" ] && 2>/dev/null
		# Create links from CDROM for UNWRITABLE (remaining) files
		/bin/cp -aus /META/var/* /var/ >/dev/null 2>&1 
		/bin/cp -aus /META/etc/* /etc/ >/dev/null 2>&1 
		# Make SURE that these are files, not links!
		/bin/rm -rf /etc/ftpusers /etc/passwd /etc/shadow /etc/group \
			/etc/ppp /etc/isdn /etc/ssh /etc/ioctl.save \
			/etc/inittab /etc/network /etc/sudoers \
			/etc/init /etc/localtime /etc/dhcpc /etc/pnm2ppa.conf >/dev/null 2>&1
		/bin/cp -a /etc/ftpusers /META/etc/passwd /META/etc/shadow /META/etc/group \
			/META/etc/ppp /META/etc/isdn /META/etc/ssh \
			/META/etc/inittab /META/etc/network /META/etc/sudoers \
			/META/sbin/init /META/etc/dhcpc /etc/ >/dev/null 2>&1
		# Extremely important, init crashes on shutdown if this is only a link
		:> /etc/ioctl.save >/dev/null 2>&1
		:> /etc/pnm2ppa.conf >/dev/null 2>&1
		# Diet libc bug workaround
		/bin/cp -f /META/etc/localtime /etc/localtime >/dev/null 2>&1
	fi

	[ "${VERBOSE}" = "yes" ] && echo "${DONEBLUE}"
}


# ------------------------------------------------------------------------------ #
# Set keymap: Get and set keymap configuration from 'var.conf'

setkeymap() {
	if [ -n ${KEYMAP} ]
        then
                [ "${VERBOSE}" = "yes" ] && echo "${BLUE}Loading ${KEYMAP} keymap${NORMAL}"
                loadkmap < /keymaps/${KEYMAP}.map
        elif
        then
                #default keymap is "us"
                [ "${VERBOSE}" = "yes" ] && echo "${BLUE}Loading default (US) keymap${NORMAL}"
                loadkmap < /keymaps/us.map
        fi
}


# ------------------------------------------------------------------------------ #
# Control progress bar
#
# Usage: progressbar number text   <-- number = %   text = message display
#        progressbar f             <-- fail
#        progressbar w             <-- warning
#

progressbar ()
{
	# Accept 1 or 2 parameters
	if [ "$#" -gt "0" ] && [ "$#" -lt "3" ] && [ "${VERBOSE}" = "no" ] && [ -f /proc/progress ]
	then
		# Normal message
		[ "$#" -eq "2" ] && ( echo ${1} ${2} > /proc/progress; return 0; )

		# Warning or fail message
		( [ ${1} = 'w' ]  || [ ${1} = 'f' ] ) && ( echo ${1} > /proc/progress; return 0; )
	else
		return 1 # fail
        fi
}]]></programlisting>
</appendix>
