# Copyright (C) 2005, 2006  Martin Michlmayr <tbm@cyrius.com>

# This code is covered by the GNU General Public License.

# Reading

# Check if a file exists and exit if it doesn't
# $1 = file
check_file() {
	if [ ! -e $1 ]; then
		log "$1 does not exist"
		exit
	fi
}

# Returns the mtd device with the specified name (without leading /dev)
# $1 = name of mtd device
get_mtd() {
	grep "\b$1\b\"*$" /proc/mtd | cut -d : -f 1
}

# Returns the mtd block device with the specified name (without leading /dev)
# $1 = name of mtd device
get_mtdblock() {
	echo $(get_mtd "$1") | sed 's/mtd/mtdblock/'
}

# Parsing

# Parse a standard Unix tree (i.e. configs found in /etc)
# $1 = root path
parse_unix_tree() {
	log "Parsing Unix tree at $1"
	ETC=$1/etc
	if [ -e $ETC/network/interfaces ]; then
		parse_network_interfaces $ETC/network/interfaces "eth0"
	fi
	if [ -e $ETC/resolv.conf ]; then
		for i in $(grep "^nameserver" $ETC/resolv.conf | sed 's/^.* //'); do
			var_add NAMESERVERS "$i"
		done
	fi
	if [ -e $ETC/hostname ]; then
		HOSTNAME=$(cat $ETC/hostname | cut -d . -f 1)
	fi
	if [ -e $ETC/domainname ]; then
		DOMAIN=$(cat $ETC/domainname)
	fi
}

# LEAF is a distro based on LRP (Linux Router Project)
# $1 = root path
parse_leaf_tree() {
	log "Parsing LEAF tree at $1"
	ETC=$1/etc
	if [ -e $ETC/resolv.static1 ]; then
		var_add NAMESERVERS "$(grep "^nameserver" $ETC/resolv.static1 | sed 's/^.* //' | head -n 1)"
	fi
	if [ -e $ETC/resolv.static2 ]; then
		var_add NAMESERVERS "$(grep "^nameserver" $ETC/resolv.static2 | sed 's/^.* //' | head -n 1)"
	fi
}

# Parse a /etc/network/interfaces file
# $1 = file
# $2 = interface
parse_network_interfaces() {
	log "Parsing $1 to find network interface $2"

	# Find the interface we're interested in
	if ! $(grep -q "^iface $2\b" $1); then
		return
	fi
	iface=$(grep -n "^iface $2\b" $1)
	if $(echo "$iface" | grep -q "inet static"); then
		n=$(echo "$iface" | cut -d : -f 1) # line number
		NET_CONFIG=static
		stanza=$(tail -n +$(($n+1)) $1)
		# Find the next interface and ignore lines from there on
		n=$(echo "$stanza" | grep -n "^iface\b" | cut -d : -f 1)
		if [ $n ]; then
			stanza=$(echo "$stanza" | head -n $(($n-1)))
		fi
		INTERFACE=$2
		IPADDRESS=$(echo "$stanza" | grep "address" | sed 's/.*address //')
		GATEWAY=$(echo "$stanza" | grep "gateway" | sed 's/.*gateway //')
	fi
}

# Parse a set of ifconfig/route/etc commands
# $1 = ifconfig et al. commands
parse_ifconfig() {
	# UGH!
	IPADDRESS=$(grep "ifconfig [-[:alpha:][:digit:]]* [[:digit:].]" $1 | sed 's/.*ifconfig [-[:alpha:][:digit:]]* \([.[:digit:]]*\) .*/\1/')
	NETMASK=$(grep '\bnetmask\b' $1 | sed 's/.*netmask\s*//' | sed 's/\s.*//')
	GATEWAY=$(grep "route add default gw" $1 | sed 's/.*gw\s*//')
}

# Get the value from a string in the form of var=value
# $1 = string
# $2 = var
get_var() {
	echo "$1" | grep "^$2=" | sed "s/^$2=//"
}

# Add a string to a variable; deals with the fact when a string is empty
# $1 = variable name
# $2 = string
var_add() {
	if [ -n "$2" ]; then
		value="$(eval echo \"$`echo $1`\")"
		if [ -n "$value" ]; then
			x="$value $2"
		else
			x="$2"
		fi
		eval "`echo $1`=\"$x\""
	fi
}

# Parse a SysConf partition, as found on the Linksys NSLU2
# $1 = path
parse_sysconf() {
	sysconf=$(devio "<<$1" cpb)
	INTERFACE=$(get_var "$sysconf" "lan_interface")
	if [ "$(get_var "$sysconf" "bootproto")" = "static" ]; then
		NET_CONFIG=static
	fi
	IPADDRESS=$(get_var "$sysconf" "ip_addr")
	NETMASK=$(get_var "$sysconf" "netmask")
	GATEWAY=$(get_var "$sysconf" "gateway")
	var_add NAMESERVERS "$(get_var "$sysconf" "dns_server1")"
	var_add NAMESERVERS "$(get_var "$sysconf" "dns_server2")"
	var_add NAMESERVERS "$(get_var "$sysconf" "dns_server3")"
	HOSTNAME=$(get_var "$sysconf" "disk_server_name")
	DEFAULT_HOSTNAME=$(get_var "$sysconf" "default_server_name")
	DOMAIN=$(get_var "$sysconf" "domain_name")
}

# Parse NVRAM variables as found on BCM947xx devices
# $1 = output of "nvram show" (i.e. a list of var=value strings)
parse_bcm947xx_nvram() {
	if [ "$(get_var "$1" "wan0_proto")" != "dhcp" ]; then
		NET_CONFIG=static
	fi
	INTERFACE=$(get_var "$1" "wan0_ifname")
	IPADDRESS=$(get_var "$1" "wan0_ipaddr")
	NETMASK=$(get_var "$1" "wan0_netmask")
	GATEWAY=$(get_var "$1" "wan_gateway_t")
	var_add NAMESERVERS "$(get_var "$1" "wan_dns_t")"
	HOSTNAME=$(get_var "$1" "lan_hostname")
	DOMAIN=$(get_var "$1" "lan_domain")
}

# Parse the NVRAM config generated by the Web Manager on Asus WL500*
# $1 = output of "nvram show" (i.e. a list of var=value strings)
parse_wl500_nvram_web_manager() {
	INTERFACE=$(get_var "$1" "wan_ifname")
	if [ "$(get_var "$1" "2_x_ConnectionType")" = "Static IP" ]; then
		NET_CONFIG=static
	fi
	if [ -n "$(get_var "$1" "5_ExternalIPAddress")" ] ; then
		IPADDRESS=$(get_var "$1" "5_ExternalIPAddress")
	else
		IPADDRESS=$(get_var "$1" "wan_ipaddr")
	fi
	NETMASK=$(get_var "$1" "4_x_ExternalSubnetMask")
	GATEWAY=$(get_var "$1" "4_x_ExternalGateway")
	if [ -n "$(get_var "$1" "4_x_DNSServerEnable")" ]; then
		if [ $(get_var "$1" "4_x_DNSServerEnable") -ne 1 ]; then
			var_add NAMESERVERS "$(get_var "$1" "4_x_DNSServer1")"
			var_add NAMESERVERS "$(get_var "$1" "4_x_DNSServer2")"
		fi
	fi
	HOSTNAME=$(get_var "$1" "9_x_HostName")
}

# Generating

# Output a variable to a preseed file if the variable has a value
# $1 = file name (stdout if this is empty)
# $2 = debconf variable name
# $3 = debconf variable type
# $4 = variable
add() {
	if [ -n "$4" -o "$3" = "note" ]; then
		if [ -n "$1" ]; then
			echo "d-i $2 $3 $4" | sed 's/ *$//' >> "$1"
		else
			echo "d-i $2 $3 $4" | sed 's/ *$//'
		fi
	fi
}

# Output a variable to a preseed file - even if the variable is empty
# $1 = file name (stdout if this is empty)
# $2 = debconf variable name
# $3 = debconf variable type
# $4 = variable
really_add() {
	if [ -z "$4" -a "$NONINTERACTIVE" = "yes" ]; then
		add "$1" "$2" "$3" '""'
	else
		add "$1" "$2" "$3" "$4"
	fi
}

# Write a static network configuration to the preseed file
# $1 = file name (stdout if this is empty)
write_static_network() {
	add "$1" "netcfg/get_ipaddress" "string" "$IPADDRESS"
	really_add "$1" "netcfg/get_netmask" "string" "$NETMASK"
	really_add "$1" "netcfg/get_gateway" "string" "$GATEWAY"
	add "$1" "netcfg/get_nameservers" "string" "$NAMESERVERS"
}

# Fall back to a static address if DHCP fails
# $1 = file name (stdout if this is empty)
dhcp_fallback() {
	add "$1" "netcfg/dhcp_failed" "note"
	add "$1" "netcfg/dhcp_options" "select" "Configure network manually"
	write_static_network "$1"
}

# Generate a preseed file
# $1 = filename
generate_preseed_file() {
	add "$1" "netcfg/choose_interface" "select" "$INTERFACE"
	if [ "$NET_CONFIG" = "static" ]; then
		write_static_network "$1"
		add "$1" "netcfg/confirm_static" "boolean" "true"
		add "$1" "netcfg/disable_dhcp" "boolean" "true"
	else
		add "$1" "netcfg/use_dhcp" "boolean" "true"
	fi
	if [ "$NONINTERACTIVE" = "yes" -o "$HOSTNAME" != "$DEFAULT_HOSTNAME" ]; then
		if verify_hostname "$HOSTNAME"; then
			add "$1" "netcfg/get_hostname" "string" "$HOSTNAME"
		fi
	fi
	add "$1" "netcfg/get_domain" "string" "$DOMAIN"
}


# Misc

# Unset a variable if it has a particular value
# $1 = variable
# $2 = value
unset_matching_var() {
	if [ "$(eval echo $`echo $1`)" = "$2" ]; then
		unset $1
	fi
}


# Check the hostname for RFC 1123 compliance.
verify_hostname() {
	t=$(echo "$1" | tr -d 'a-zA-Z0-9.-')
	if [ -n "$t" ]; then
		return 1
	fi
	if echo "$1" | grep -q "^-"; then
		return 1
	fi
	if echo "$1" | grep -q -- "-$"; then
		return 1
	fi
	l=$(($(echo "$1" | wc -c) - 1))
	if [ $l -lt 2 -o $l -gt 63 ]; then
		return 1
	fi
	return 0
}

