#! /bin/sh

#set -o errexit
#set -o nounset
#set -o xtrace

V=0.50	# initial
V=0.51	# exclude fake Supermicro serial numbers
V=0.52	# VMware serial number mangling
V=0.60	# refactored into separate query modules of decreasing priority 
V=0.61	# exclude Ethernet NICs that have lost their hardware address
V=0.62	# SSH fingerprint is not valid on new hardware setup
V=0.63	# support for Cobalt RaQ serialnumber
V=0.64	# exclude fake PC Engines serial number (DMI)
V=0.65	# support for PC Engines serial number (from MAC address of the first NIC)
V=0.66	# remove SPARC support
V=0.67	# exclude fake AAEON serial number ("To be filled by O.E.M.")
V=0.68	# unify DMI system and baseboard query procedures
V=0.69	# move serial number filtering to DMI processing only
V=0.70	# add dmi_chassis scan
V=0.71	# blacklist fake 'Default string' serial number

remove_whitespace () {
	STRING="$1"
	while test "$STRING" != "${STRING## }"
	do
		STRING="${STRING## }"
	done
	echo "$STRING"
}

query_dmi () {
	which dmidecode >/dev/null || return
	local OBJECT SERIAL
	OBJECT=$1
	SERIAL=$(dmidecode --string $OBJECT-serial-number|awk '{if (substr($0,1,1)=="#"){next}{print}}')
	case "$SERIAL" in
		VMware-*)
			SERIAL=${SERIAL#VMware-}
			SERIAL=$(echo "$SERIAL"|tr --delete ' ')
			;;
		'To Be Filled By O.E.M.'|'To be filled by O.E.M.')
			return
			;;
		'0123456789'|'1234567890'|'123456789')
			return
			;;
		'0'|'000000000000')
			return
			;;
		'None'|'Not Specified')
			return
			;;
		'Default string')
			return
			;;
	esac

	SERIAL=$(remove_whitespace "$SERIAL")
	echo $SERIAL
}

query_dmi_system () {
	query_dmi system
}

query_dmi_baseboard () {
	query_dmi baseboard
}

query_dmi_chassis () {
	query_dmi chassis
}

query_cobalt () {
	test -d '/proc/cobalt' || return
	cat '/proc/cobalt/serialnumber'
}

query_pc_engines () {
	which dmidecode >/dev/null || return
	SYSTEM_MANUFACTURER=$(dmidecode --string system-manufacturer)
	test "$SYSTEM_MANUFACTURER" = 'PC Engines' || return
	VENDOR=$(ip link show|awk '{if($1=="link/ether"){split($2,mac,":");print mac[1]mac[2]mac[3];exit}}')
	test "$VENDOR" = '000db9' || return

	#http://pcengines.ch/howto.htm#macadr
	#serial = (MAC ID & 0x000000FFFFFF) / 4 - 64
	ip link show | awk --non-decimal-data '{if($1=="link/ether"){
	split($2,mac_addr,":")
	mac_id=sprintf("%d","0x" mac_addr[4]mac_addr[5]mac_addr[6])
	print mac_id/4-64
  	exit}}'
}


query_first_nic () {
	test "$(stat -c %d:%i /)" != "$(stat -c %d:%i /proc/1/root/.)" && return #chroot
	test -d '/sys/bus/xen/drivers/vif' && return
	ip link show|awk '{if($1=="link/ether"){gsub(":","",$2);print $2;exit}}'
}

query_bcfg2_uuid () {
	test -s '/etc/bcfg2.conf' || return
	awk -F' = ' '{
	if (match($1,"[[]([[:alpha:]]+)[]]",line))
		section=line[1]
	else if (section=="communication" && $1=="user")
		print $2
	}' '/etc/bcfg2.conf'
}

query_ssh_fingerprint () {
	test -s '/etc/debian_version' || return
	ssh-keygen -r @|awk '{if ($1$2$3$4$5 == "@INSSHFP11"){print $6}}'
}


for MODULE in cobalt pc_engines dmi_system dmi_chassis dmi_baseboard first_nic bcfg2_uuid ssh_fingerprint
do
	SERIAL=$(eval "query_$MODULE")
	test -n "$SERIAL" && break
done

test -n "$SERIAL" && echo -n $SERIAL
