system_information.sh 7.9 KB
#!/bin/dash

##
# This is a first test what static informations I can gather from a
# system. The minimal requirement are the IP addresses because
# on these I build up my classes.
# The system type is also important...we might need to be running
# on variuous UNIX flavours. (But for now we focus on various linux
# flavours and maybe FreeBSD.
#


# Function calculates number of bit in a netmask
#
mask2cidr() {
	local NBITS=0
	local OLDIFS="${IFS}"
	IFS=.

	for DEC in $1
	do
		case ${DEC} in
			255) NBITS=$((NBITS+8));;
			254) NBITS=$((NBITS+7));;
			252) NBITS=$((NBITS+6));;
			248) NBITS=$((NBITS+5));;
			240) NBITS=$((NBITS+4));;
			224) NBITS=$((NBITS+3));;
			192) NBITS=$((NBITS+2));;
			128) NBITS=$((NBITS+1));;
			0);;
			*) NBITS=0; IFS="${OLDIFS}"; return 1
		esac
	done
	IFS="${OLDIFS}"
	${ECHO} "${NBITS}"
}

cidr2mask() {
	local MASK=""
	local FULL_OCTETS=$((${1}/8))
	local PARTIAL_OCTET=$((${1}%8))

	for I in 0 1 2 3
	do
		if [ ${I} -lt ${FULL_OCTETS} ]
		then
			MASK="${MASK}255"
		elif [ ${I} -eq ${FULL_OCTETS} ]
		then
			MASK="${MASK}$((256-(1<<(8-${PARTIAL_OCTET}))))"
		else
			MASK="${MASK}0"
		fi  
		${TEST} ${I} -lt 3 && MASK="${MASK}."
	done

	${ECHO} ${MASK}
}

##
# retrieve interfaces. I prefer using ip if it is
# available, else I fallback to ifconfig... don't know
# how to retrieve this information on other systems.
#
get_if_data() {
	if [ ${IP} ]
	then
		eval $(${IP} -o link | ${AWK} '{
			sub(/:/,"",$1);
			no=$1;
			sub(/:/,"",$2);
			name=$2;
			for (i=3; i<NF; i++) {
				if ($i == "state") {
					i++; state=$i
				}
				if ($i ~ /link/) {
					i++; mac=$i;
					classes=classes mac " "
				}
			}
			print "IF" no "_NAME=" name ";IF" no "_STATE=" state ";IF" no "_MAC=" mac ";";
			if ("UP" == state) classes=classes mac " "
		}
		BEGIN {
			classes=""
		}
		END {
			print "CLASSES=\"${CLASSES}" classes " \";";
			print "NINTERFACES=" FNR ";"
		}')

		eval $(${IP} -o addr | ${AWK} '{
			sub(/:/,"",$1);
			no=$1;
			if ($3 == "inet") {
				sub(/[\/%].*/,"",$4);
				print "IF" no "_IPV4=\"${IF" no "_IPV4}" $4 " \";";
				classes=classes $4 " "
			}
			if ($3 == "inet6") {
				sub(/[\/%].*/,"",$4);
				print "IF" no "_IPV6=\"${IF" no "_IPV6}" $4 " \";";
				classes=classes $4 " "
			}
		}
		BEGIN {
			classes=""
		}
		END {
			print "CLASSES=\"${CLASSES}" classes " \";"
		}')
	else
		if [ ${IFCONFIG} ]
		then
			#eval $(${IFCONFIG} -a | ${AWK} '{
			eval $(ifconfig -a | awk '
			/ether/ { mac=$2 }
			/inet / { ipv4=ipv4 $2 " " }
			/inet6/ { ipv6=ipv6 $2 " " }
			/^[^ \t]/ {
				if ("" != ipv4 || "" != ipv6) state="UP"; else state="DOWN";
				if ("" != name) {
					print "IF" no "_NAME=" name ";IF" no "_STATE=" state ";IF" no "_MAC=" mac ";" \
						"IF" no "_IPV4=\"${IF" no "_IPV4}" ipv4 " \";" \
						"IF" no "_IPV6=\"${IF" no "_IPV6}" ipv6 " \";";
					no++;
				}
				ipv4=ipv6="";
				sub(/:/,"",$1);
				name=$1
			}
			BEGIN {
				no=1;
			}
			END {
				if ("" != ipv4 || "" != ipv6) state="UP"; else state="DOWN";
				print "IF" no "_NAME=" name ";IF" no "_STATE=" state ";IF" no "_MAC=" mac ";" \
					"IF" no "_IPV4=\"${IF" no "_IPV4}" ipv4 " \";" \
					"IF" no "_IPV6=\"${IF" no "_IPV6}" ipv6 " \";";
				print "NINTERFACES=" no
			}')
		else
			${LOGGER} -p local0.warn 'Found no way to retrieve interface information.'
		fi
	fi
}

##
# start guessing the system type
# 1. get informations via uname
#
get_host_info() {
	OS="$(${UNAME} -o)"
	KERNEL="$(${UNAME} -s)"
	VERSION="$(${UNAME} -r)"
	PLATFORM="$(${UNAME} -m)"
	HOSTNAME="$(${UNAME} -n)"
	CLASSES="$(${ECHO} -e "${OS}\n${KERNEL}\n${VERSION}\n${PLATFORM}\n${HOSTNAME}" |\
		${SORT} -u | ${TR} "\n" " ")"
}

##
# if we are on a linux try to figure out wich distribution we are
# running.
# First look what kind of realease file we have:
#   
#   00 01 - Novell SuSE   ---> /etc/SuSE-release
#   00 02 - Red Hat       ---> /etc/redhat-release, /etc/redhat_version
#   00 04 - Fedora        ---> /etc/fedora-release
#   00 08 - Slackware     ---> /etc/slackware-release, /etc/slackware-version
#   00 10 - Debian        ---> /etc/debian_release, /etc/debian_version
#   00 20 - Mandrake      ---> /etc/mandrake-release
#   00 40 - Yellow dog    ---> /etc/yellowdog-release
#   00 80 - Sun JDS       ---> /etc/sun-release
#   01 00 - Solaris/Sparc ---> /etc/release
#   02 00 - Gentoo        ---> /etc/gentoo-release
#
# Here I follow a pessimistic way because I prefere to have no
# identification at all over a wrong one...so I check for all these files.
# If I can't find any or find multiple of them I assume this system
# as unidentified. Anyway when I found one I still check the content...
# Here I need some help as I don't know the valid content of these files.
# For now I assume that at least the name of the distribution is in
# the file.
#
get_dist_info() {
	if [ -z "${KERNEL}" ]
	then
		get_host_info
	fi

	if [ "Linux" = "${KERNEL}" ]
	then
		local SUSE=1
		local REDHAT=2
		local FEDORA=4
		local SLACKWARE=8
		local DEBIAN=16
		local MANDRAKE=32
		local YELLOWDOG=64
		local SUNJDS=128
		local GENTOO=256
		local SOLARIS=512

		local LAST=${SOLARIS}

		local CHK=$((SUSE|REDHAT|FEDORA|SLACKWARE|DEBIAN|MANDRAKE|\
			YELLOWDOG|SUNJDS|GENTOO|SOLARIS))

		eval local FILES_${SUSE}=\'/etc/SuSE-release\'
		eval local FILES_${REDHAT}=\'/etc/redhat-release /etc/redhat_version\'
		eval local FILES_${FEDORA}=\'/etc/fedora-release\'
		eval local FILES_${SLACKWARE}=\'/etc/slackware-release /etc/slackware-version\'
		eval local FILES_${DEBIAN}=\'/etc/debian_release /etc/debian_version\'
		eval local FILES_${MANDRAKE}=\'/etc/mandrake-release\'
		eval local FILES_${YELLOWDOG}=\'/etc/yellowdog-release\'
		eval local FILES_${SUNJDS}=\'/etc/sun-release\'
		eval local FILES_${GENTOO}=\'/etc/gentoo-release\'
		eval local FILES_${SOLARIS}=\'/etc/release\'

		local CUR=1
		while [ ${CUR} -le ${LAST} ]
		do
			local DIR

			eval local FILES=\"\${FILES_${CUR}}\"

			for DIR in ${FILES}
			do
				${TEST} -f ${DIR} || CHK=$((CHK&~CUR))
			done

			CUR=$((CUR*2))
		done

		DIST="Unknown"

		${TEST} ${CHK} -eq ${SUSE}      && DIST="Suse"
		${TEST} ${CHK} -eq ${REDHAT}    && DIST="Redhat"
		${TEST} ${CHK} -eq ${FEDORA}    && DIST="Fedora"
		${TEST} ${CHK} -eq ${SLACKWARE} && DIST="Slakware"
		${TEST} ${CHK} -eq ${DEBIAN}    && DIST="Debian"
		${TEST} ${CHK} -eq ${MANDRAKE}  && DIST="Mandrake"
		${TEST} ${CHK} -eq ${YELLOWDOG} && DIST="Yellowdog"
		${TEST} ${CHK} -eq ${SUNJDS}    && DIST="Sun"
		${TEST} ${CHK} -eq ${GENTOO}    && DIST="Gentoo"
		${TEST} ${CHK} -eq ${SOLARIS}   && DIST="Solaris"

		if [ 'Unknown' != "${DIST}" ]
		then
			eval ${GREP} -iq ${DIST} \${FILES_${CHK}} || DIST="Unknown"
		fi

		CLASSES="${CLASSES}${DIST} "
	else
		DIST="${OS}"
	fi
}

##
# Here now starts the usage of the functions defined above.
#

##
# first specify some programs
#
WHICH="/usr/bin/which"
UNAME="$(${WHICH} uname)"
TEST="$(${WHICH} test)"
GREP="$(${WHICH} grep)"
AWK="$(${WHICH} awk)"
ECHO="$(${WHICH} echo)"
SORT="$(${WHICH} sort)"
TR="$(${WHICH} tr)"
PRINTF="$(${WHICH} printf)"
LOGGER="$(${WHICH} logger)"
IP="$(${WHICH} ip)"
IFCONFIG="$(${WHICH} ifconfig)"

get_dist_info
get_if_data

##
# report everysthing
#

${PRINTF} "%15s : %s\n" "OS" "${OS}"
${PRINTF} "%15s : %s\n" "KERNEL" "${KERNEL}"
${PRINTF} "%15s : %s\n" "VERSION" "${VERSION}"
${PRINTF} "%15s : %s\n" "PLATFORM" "${PLATFORM}"
${PRINTF} "%15s : %s\n" "DIST" "${DIST}"
${PRINTF} "%15s : %s\n" "HOSTNAME" "${HOSTNAME}"
${PRINTF} "%15s : %s\n" "# INTERFACES" "${NINTERFACES}"

NO=1
while [ ${NO} -le ${NINTERFACES:=0} ]
do
	eval printf \"%15s : %s\\\n\" \"IF${NO}_NAME\" \"\${IF${NO}_NAME}\"
	eval printf \"%15s : %s\\\n\" \"IF${NO}_MAC\" \"\${IF${NO}_MAC}\"
	eval printf \"%15s : %s\\\n\" \"IF${NO}_STATE\" \"\${IF${NO}_STATE}\"
	eval printf \"%15s : %s\\\n\" \"IF${NO}_IPV4\" \"\${IF${NO}_IPV4}\"
	eval printf \"%15s : %s\\\n\" \"IF${NO}_IPV6\" \"\${IF${NO}_IPV6}\"
	NO=$((NO+1))
done

${PRINTF} "%15s : %s\n" "CLASSES" "${CLASSES}"

echo
echo $(mask2cidr 255.255.128.0)
echo $(cidr2mask 17)
eval echo \$\(cidr2mask $(mask2cidr 255.255.128.0)\)

# vim: set ts=4 sw=4: