#!/bin/sh

# Shell script to collect kernel data.
# Copyright (C) 2001-2004 Open Challenge B.V.
# Copyright (C) 2004 OpenEyeT Professional Services.
#
# 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, 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; see the file COPYING.
# If not, write to the Free Software Foundation,
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# Contact information: www.OpenEyeT.nl/scc/index.html 

# This is a system module of scc, to call it separately in the
# proper environment, use: scc-collect -i -e <module_name>

# SCC-release:	1.6.26
# file-version:	$Revision: 1.33 $
 
. ${SCC_BIN}/scc_modules/scc_utils

scc_check_file /etc/system "fix:kernel:/etc/system::" "\*"
scc_check_file /stand/kernrel "fix:kernel:/stand/kernrel::" "#"
scc_check_file /stand/system "fix:kernel:/stand/system::" "#"
scc_check_file /etc/lkm.conf "fix:kernel:/etc/lkm.conf::" "#"

if [ -x /sbin/kernelversion ]
then
	/sbin/kernelversion 2>/dev/null		|
	sed -e 's/^/fix:kernel:kernelversion::/'
fi

for f in ioconfig rootconf vmunix
do
	if [ -f /stand/${f} ]
	then
		# Harry van Wiggen indicated changes in /stand/ioconfig after using the command ioscan.
		# Erase the binary data and sort to avoid these unwanted changes in the logbook.
		echo "fix:kernel:/stand/${f}::cksum:	$(strings /stand/${f} | sort | cksum)"
	fi
done

if [ "${OS_NAME}" = "HP-UX" ]
then
	# For HP-UX 10.20 this will not work when we are not
	# running the default kernel: /stand/vmunix. In that case
	# other programs like ioscan and lanscan will not work either and the
	# snapshot will be incomplete.
	# We do not correct for this particular case.
	scc_help_info "hlp:kernel:boot-disk::" <<-_X_
		Specific for HP-UX.
		Use adb to obtain the value for boot_string from
		the kernel ${HPUX_KERNEL}
	_X_
	echo 'boot_string/S'					|
	/usr/bin/adb "${HPUX_KERNEL}" /dev/kmem 2>/dev/null	|
	sed -n	-e 's/^/fix:kernel:boot-disk::/'	\
		-e 's@/@/@p'

	# Ignore header files. On HP-UX 11i, some header files occur very often.
	/usr/bin/what ${HPUX_KERNEL}				|
	sed	-e 's/^[ 	]*//'	\
		-e '/^$/d'		\
		-e '/\.h[ 	]/d'	\
		-e "s@^@fix:kernel:${HPUX_KERNEL}::@"	|
	sort
fi

if [ -x /usr/sbin/sizer ]
then
	echo "fix:kernel:running::$(/usr/sbin/sizer -b 2>/dev/null)"
fi

if [ -x /usr/sbin/lsdev ]
then
	options=""
	if [ "${OS_NAME}" = "AIX" ]
	then
		options="-C -H"
	fi
	/usr/sbin/lsdev ${options} 2>/dev/null			|
	sed -e 's/^/fix:kernel:lsdev::/'
fi

if [ -x /usr/sbin/kconfig ]
then
	# Manage kernel configurations.
	/usr/sbin/kconfig -v 2>/dev/null		|
	sed	-e 's/^/fix:kernel:kconfig::/'	\
		-e 's/fix:\(.* Time \)/var:\1/'
fi

if [ -f /stand/system -a -x /usr/lbin/sysadm/system_prep ]
then
	scc_help_info "hlp:kernel:mk_kernel::" <<-_X_
		Specific for HP-UX.
		When a new kernel is compiled via SAM, the command
		system_prep generates the file /stand/system.
		Anyone who edits this file directly to change a new kernel,
		will loose the changes when SAM is used to generate a new kernel.
		scc compares the output of system_prep with the contents of the file /stand/system.
		Differences are reported.
	_X_
	/usr/lbin/sysadm/system_prep -s ${TMP1_FILE} >/dev/null
	sed	-e 's/[ 	][ 	]*/ /g'	\
		-e 's/ 0X/ 0x/g'		\
			<${TMP1_FILE}		\
			>${TMP2_FILE}
	sed	-e 's/[ 	][ 	]*/ /g'	\
		-e 's/ 0X/ 0x/g'		\
			</stand/system		\
			>${TMP3_FILE}
	
	cmp -s ${TMP2_FILE} ${TMP3_FILE}
	if [ $? -eq 0 ]
	then
		echo "fix:kernel:mk_kernel::status:	${HPUX_KERNEL}-/stand/system identical"
	else
		echo "fix:kernel:mk_kernel::status:	${HPUX_KERNEL}-/stand/system different"

		diff ${TMP2_FILE} ${TMP3_FILE}			|
		sed	-e '/^[0-9\-]/d'                				\
			-e "s@< @fix:kernel:mk_kernel::/usr/conf/master.d	:@"	\
			-e "s@> @fix:kernel:mk_kernel::/stand/system		:@"

	fi
	rm -f ${TMP1_FILE} ${TMP2_FILE} ${TMP3_FILE}
fi

if [ -x /usr/sbin/kmadmin ]
then
	/usr/sbin/kmadmin -s			|
	sed -e 's/^/fix:kernel:kmadmin:short::/'

	/usr/sbin/kmadmin -S			|
	sed -e 's/^/var:kernel:kmadmin:full::/'
fi

if [ -x /usr/sbin/kmsystem ]
then
	/usr/sbin/kmsystem			|
	sed -e 's/^/fix:kernel:kmsystem::/'
fi

if [ -x /usr/sbin/kmtune ]
then
	# Dynamic variables can be altered without rebooting.
	# They are treated as fix as we want to know when they are changed.
	/usr/sbin/kmtune -l				|
	awk '/^$/	{
				printf( "fix:kernel:kmtune:%s\n", parms );
				parms="";
				next
			}
			{ parms=sprintf( "%s:%s", parms, $2 ); }
	END     {
			if ( length( parms ) > 0 )
			{
				printf( "fix:kernel:kmtune:%s\n", parms );
			}
		}'
fi

if [ -x /sbin/ksyms ]
then
	# Remove the offset.
	/sbin/ksyms -m 2>/dev/null				|
	sed	-e 's/^[^ ][^ ]*  *//'	\
		-e 's/^/var:kernel:modules:ksyms::/'
fi

if [ -x /usr/sbin/modinfo ]
then
	/usr/sbin/modinfo					|
	sed -e 's/^/var:kernel:modules:modinfo::/'
fi

if [ -x /sbin/modprobe ]
then
	# On some systems, the output of the next command can be huge due to the alias lines.
	/sbin/modprobe -c			|
	sed	-e '/^alias /d'		\
		-e '/^[ 	]*$/d'	\
		-e '/^#/d'		\
		-e 's/^/fix:kernel:modules:modprobe-config::/'

	/sbin/modprobe -l 2>${TMP1_FILE}			|
	awk -F/ '{
			# Each full path of a module usually contains the version-ID
			# of the kernel. Record the base-directory first and then remove
			# it from the module-list. This reduces the amount of output
			# when comparing kernel-parts of snapshots.
			if ( NR == 1 )
			{
				printf( "%s::basepath:	/%s/%s/%s\n", l, $2, $3, $4 );
			}

			printf( "%s::%s/%s", l, $5, $6 );
			for ( i = 7; i <= NF; i++ )
			{
				printf( "/%s", $i );
			}
			printf( "\n" );
		}' l="fix:kernel:modules:modprobe-list"

	if [ -s ${TMP1_FILE} ]
	then
		sed -e "s/^/fix:kernel:modules:modprobe messages::/" ${TMP1_FILE}
	fi
	rm -f ${TMP1_FILE}
fi

if [ -x /usr/bin/modstat ]
then
	/usr/bin/modstat 2>/dev/null			|
	sed -e 's/^/fix:kernel:modules:modstat::/'
fi

if [ -x /sbin/sysconfig ]
then
	/sbin/sysconfig -s 2>&1				|
	sed -e 's/^/fix:kernel:modules:sysconfig::/'
fi

if [ -x /usr/sbin/sizer ]
then
	/usr/sbin/sizer -m 2>/dev/null			|
	sed -e 's/^/fix:kernel:modules:sizer::/'

	/usr/sbin/sizer -M 2>/dev/null			|
	sed -e 's/^/fix:kernel:foreign kit:sizer::/'
fi

scc_check_file /etc/modules.conf "fix:kernel:modules:/etc/modules.conf::" "#"
scc_check_file /etc/conf.modules "fix:kernel:modules:/etc/conf.modules::" "#"
scc_check_file /etc/sysconfigtab "fix:kernel:modules:/etc/sysconfigtab::" "#"

for f in /kernel/drv/*.conf
do
	scc_check_file "${f}" "fix:kernel:/kernel/drv:$(basename "${f}")::" "#"
done

if [ "${OS_NAME}" = "OSF1" ]
then
	myhost="$(hostname | sed -e 's/\..*//' | tr "[a-z]" "[A-Z]")"
	scc_check_file /sys/conf/${myhost} "fix:kernel:config:/sys/conf/${myhost}::" "#"
fi

if [ -x /usr/sbin/lsattr ]
then
	/usr/sbin/lsattr -E -l sys0		|
	sed -e 's/^/fix:kernel:parameters lsattr::/'
fi

if [ -d /boot ]
then
	# The name of the config file is determined by the administrator.
	# Convention is config<kernel-id> or .config<kernel-id>.
	# Look for the most recent file.
	cfg="$(ls -t /boot/config* /boot/.config* 2>/dev/null | head -1)"
	if [ -f "${cfg}" ]
	then
		echo "fix:kernel:parameters::filename:${cfg}"
		sed	-e '/^#/d'		\
			-e '/^[ 	]*$/d'	\
			-e 's/^/fix:kernel:parameters::/' "${cfg}"
	fi
fi

if [ -x /usr/sbin/sysdef ]
then
	if [ "${OS_NAME}" = "HP-UX" ]
	then
		# Use sysdef only for HP-UX 10.20 as it is being replaced by kmtune.
		if [ ! -x /usr/sbin/kmtune ]
		then
			/usr/sbin/sysdef 2>/dev/null			|
			sort						|
			sed	-e '/^bufpages/d'	\
				-e '/^\*/d'		\
				-e '/^msgmap/d'		\
				-e '/^nbuf/d'		\
				-e '/^semmap/d'		\
				-e 's/^/fix:kernel:sysdef::/'
		fi
	else
		# Each zone that is booted on Solaris 10, has its own zcons instance.
		# Change to var to avoid changes in the logbook.
		/usr/sbin/sysdef -D 2>/dev/null				|
		sed	-e '/^\//d'			\
			-e 's/^/fix:kernel:sysdef::/'	\
			-e 's/fix:\(.*zcons, instance #\)/var:\1/'
	fi
fi

if [ -x /sbin/sysctl ]
then
	case "${OS_NAME}" in
	*BSD)	KERNEL="kern"
		;;
	*)	KERNEL="kernel"
		;;
	esac

	# Only keep the kernel-stuff and ignore variable data.
	sysctl -a 2>/dev/null									|
	sed -n										\
		-e "/${KERNEL}\.arandom/d"						\
		-e "/${KERNEL}\.cp_time/d"						\
		-e "/${KERNEL}\.devstat.generation/d"					\
		-e "/${KERNEL}\.forkstat/d"						\
		-e "/${KERNEL}\.ipc.numopensockets/d"					\
		-e "/${KERNEL}\.ipc.nsfbufspeak/d"					\
		-e "/${KERNEL}\.ipc.pipekva/d"						\
		-e "/${KERNEL}\.ipc.pipes/d"						\
		-e "/${KERNEL}\.lastpid/d"						\
		-e "/${KERNEL}\.malloc.bucket/d"					\
		-e "/${KERNEL}\.malloc.kmemstat/d"					\
		-e "/${KERNEL}\.nchstats/d"						\
		-e "/${KERNEL}\.nfiles/d"						\
		-e "/${KERNEL}\.nprocs/d"						\
		-e "/${KERNEL}\.openfiles/d"						\
		-e "/${KERNEL}\.pipe\.kvasize/d"					\
		-e "/${KERNEL}\.pty\.nr/d"						\
		-e "/${KERNEL}\.random/d"						\
		-e "/${KERNEL}\.rtsig-nr/d"						\
		-e "/${KERNEL}\.timecounter/d"						\
		-e "/${KERNEL}\.tkstat/d"						\
		-e "/${KERNEL}\.boottime/d"						\
		-e "/${KERNEL}\.tty[_\.]/d"						\
		-e "s/^${KERNEL}\./fix:kernel:sysctl::${KERNEL}./p"				|
	sort
fi

exit 0
