#!/bin/sh -e
#
# Copyright (C) 2000-2003  Dmitry V. Levin <ldv@altlinux.org>
# Copyright (C) 2003 Peter Novodvorsky <nidd@altlinux.com>
#
# Linux kernel headers version selection utility.
#
# 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 of the License, 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; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#

PROG="${0##*/}"

fatal()
{
	echo "${0##*/}: $*" >&2
	exit 1
}

list_kernels()
{
	local list1="$(/bin/ls -d1 /usr/include/linux-*/include/linux/version.h 2>/dev/null |
		while read f; do
			find "$f" -maxdepth 1 -type f -size +100c 2>/dev/null
		done |
		sed -e 's,^/usr/include/linux-\([^/]\+\)/include/linux/version\.h$,\1,g')"
	local list2="$(/bin/ls -d1 /usr/lib/kernel/2.*/include/linux/version.h 2>/dev/null |
		while read f; do
			find "$f" -maxdepth 1 -type f -size +100c 2>/dev/null
		done |
		sed -e 's,^/usr/lib/kernel/\([^/]\+\)/include/linux/version\.h$,\1,g')"
	local list3="$(/bin/ls -d1 /var/lib/kernel/2.*/version.h 2>/dev/null |
		while read f; do
			find "$f" -maxdepth 1 -type f -size +100c 2>/dev/null
		done |
		sed -e 's,^/var/lib/kernel/\([^/]\+\)/version\.h$,\1,g')"
	local list4="$(/bin/ls -d1 /usr/lib/kernel/2.*/version.h 2>/dev/null |
		while read f; do
			find "$f" -maxdepth 1 -type f -size +100c 2>/dev/null
		done |
		sed -e 's,^/usr/lib/kernel/\([^/]\+\)/version\.h$,\1,g')"
	(echo "$list1"; echo "$list2"; echo "$list3"; echo "$list4") |
		sort -u |
		grep -v '^$'
}

usage()
{
	echo "Usage: $PROG {$(list_kernels |xargs echo auto |tr ' ' '|')}" >&2
	exit $1
}

gen_kernel_hdrs()
{
	local destdir=/var/run/kernel
	cd "$destdir" && [ -w . ]

	local dir=$1
	shift

	local n
	for n in autoconf modversions version; do
		local inc_line="#include <$dir/$n.h>"
		fgrep -qs "$inc_line" "$n.h" ||
		cat >"$n.h" << EOF
/*
 * Autogenerated by $PROG at $(LANG=C date '+%a %b %d %Y %T')
 */

#ifndef	__boot_kernel_${n}__
#define	__boot_kernel_${n}__

$inc_line

#endif	/* __boot_kernel_${n}__ */
EOF
	done

	H2PH=/usr/bin/h2ph
	if [ -x "$H2PH" ]; then
		"$H2PH" -l -Q -d "$destdir" {autoconf,modversions,version}.h ||:
	fi
}

KERNEL_INCLUDE=/etc/sysconfig/kernel/include

try_adjust_new()
{
	local dir="$1"
	shift

	local f="$dir/include/linux/version.h"
	if [ -f "$f" ] && [ -n "$(find "$f" -maxdepth 1 -type f -size +100c 2>/dev/null)" ]; then
		ln -snf "$dir/include" "$KERNEL_INCLUDE"
		exit $?
	fi
}

try_adjust_old()
{
	local dir="$1"
	shift

	local f="$dir/version.h"
	if [ -f "$f" ] && [ -n "$(find "$f" -maxdepth 1 -type f -size +100c 2>/dev/null)" ]; then
		ln -snf /usr/lib/kernel/include "$KERNEL_INCLUDE"
		gen_kernel_hdrs "$dir"
		exit $?
	fi
}

try_adjust_all()
{
	try_adjust_new "/usr/include/linux-$1"
	try_adjust_new "/usr/lib/kernel/$1"
	try_adjust_old "/var/lib/kernel/$1"
	try_adjust_old "/usr/lib/kernel/$1"
}

case "$1" in
	help|--help|usage|--usage)
		usage 0
		;;
	list|--list)
		list_kernels
		exit 0
		;;
	first|--first)
		first="$(list_kernels |head -1)"
		[ -z "$first" ] || try_adjust_all "$first"
		fatal "$1: unable to find \"first\" kernel headers"
		;;
	''|auto|--auto)
		;;
	*)
		[ -n "${1##*/*}" ] && [ "$1" = default -o -z "${1##[2-9]*}" ] || fatal "invalid kernel version: $1"
		try_adjust_all "$1"
		fatal "$1: kernel headers for this version are not installed"
		;;
esac

FULL_KERNEL_VERSION="$(uname -r)"
KERNEL_VERSION="$(echo "$FULL_KERNEL_VERSION"| sed -e 's/-alt[[:digit:]]\+\(\.[[:digit:]]\+\)\?//')"

try_adjust_new "/usr/include/linux-$KERNEL_VERSION"

try_adjust_new "/usr/lib/kernel/$KERNEL_VERSION"

try_adjust_old "/var/lib/kernel/$FULL_KERNEL_VERSION"

try_adjust_old "/usr/lib/kernel/$FULL_KERNEL_VERSION"

try_adjust_new /usr/include/linux-default

exit 1
