#!/bin/sh

#-
# Copyright 2006 Ricardo A. Reis ricardo.areis@gmail.com
# All rights reserved
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted providing that the following conditions 
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

SEARCH_PATH=`kldconfig -r |tr ';' ' '`
EXIT_ERROR="1"
EXIT_OK="0"
EXIT_USAGE="64"
LOCAL_VERSION="0.61"

usage()
{
cat <<EOF
usage: `basename $0` [-qv] -c category ...
       `basename $0` [-qv] -s string   ...
       `basename $0`  -h
EOF
exit $EXIT_USAGE
}

help()
{
cat <<EOF
kldfind Version $LOCAL_VERSION
Options:
  -c	--  find all matchs for category
  -s	--  string match
  -v    --  verbose 
  -q    --  quiet  
EOF
exit $EXIT_USAGE
}
output()
{
OUT="$1"
RESULT="$2"
SEARCH_PATH="$3"
NUMBER_R=`echo $RESULT | tr ' ' '\n' |grep .|wc -l|sed -e 's/ //g'`
if [ "$OUT" = "VERBOSE" ];then
    if [ $NUMBER_R -ne 0 ];then
        cat <<EOF


====>   Search finished, $NUMBER_R resultes for $SEARCH_PATH

EOF
printf  "\n%-15s \t\t%s" "       KLD" "    Description"
printf  "\n%-15s \t\t%s" "       ---" "    -----------"
echo ""
    for _result in $RESULT;do
        if man ${_result} >/dev/null 2>&1;then
            SHORT_DESC=`man ${_result} |col -b|awk '/^NAME/,/-/ { gsub(/^.* [-]+ |(  )+|^[ ]+|--$/,"") ; print  }'|\
                tail -n1 |tr '\n' ' ' 2>&1`
        else
            SHORT_DESC="No manual entry for ${_result}"
        fi
        printf  "\n%-15s \t\t%s" "===>   $_result," "--- $SHORT_DESC"
    done
   	    return $EXIT_OK
    fi
fi
if [ ! -z "$RESULT" -a -z $SEARCH_PATH  ];then
    if   [ "$OUT" = "SHORT" ];then
            echo "$RESULT"
    	    exit  $EXIT_OK
    elif [ "$OUT" = "QUIET" ];then
            exit  $EXIT_OK
    fi
else
    exit $EXIT_ERROR
fi
}

search()
{
OUT="$1";shift
TYPE="$1";shift
STRING="$1";shift
if [ $OUT = "QUIET" ];then
    if [ -d $_search_path ];then
        if   [ $TYPE = "c" ];then
            KLD=`find ${SEARCH_PATH} -iregex ".*/${STRING}_.*" -print | sed -e 's#^.*/## ; s#.ko##'`
        elif [ $TYPE = "s" ];then
            KLD=`find ${SEARCH_PATH} -iname  "*${STRING}*" -print | sed -e 's#^.*/## ; s#.ko##'`
        fi
			output $OUT "$KLD" 
    fi
fi
if [ $OUT = "SHORT" ];then
    if [ -d $_search_path ];then
        if   [ $TYPE = "c" ];then
            KLD=`find ${SEARCH_PATH}  -iregex  ".*/${STRING}_.*" -print`
        elif [ $TYPE = "s" ];then
            KLD=`find ${SEARCH_PATH} -iname   "*${STRING}*" -print`
        fi
			output $OUT "$KLD"
    fi
fi
for _search_path in ${SEARCH_PATH};do
	if [ -d $_search_path ];then
		if   [ $TYPE = "c" ];then
			KLD=`find $_search_path -iregex  ".*/${STRING}_.*" -print | sed -e 's#^.*/## ; s#.ko##'`
		elif [ $TYPE = "s" ];then
			KLD=`find $_search_path -iname   "*${STRING}*" -print | sed -e 's#^.*/## ; s#.ko##'`
		fi
			output $OUT "$KLD" "$_search_path"
	fi
done
}
set_out()
{
# if output option is set after c or s options
#getopt failt in set default output.
THIRD_ARG=${1}

if [ ! -z $THIRD_ARG ];then
    if   [ ${THIRD_ARG} != "-v" -a ${THIRD_ARG} != "-q" ];then
        VERBOSE=${VERBOSE:-0}
        QUIET=${QUIET:-0}
	elif [ ${THIRD_ARG}  = "-v" ];then
		VERBOSE=1
	elif [ ${THIRD_ARG}  = "-q" ];then
		QUIET=1
	else
		usage
	fi
fi

if   [ ${VERBOSE:-0} -eq 1 -a ${QUIET:-0} -eq 1 ];then
	    usage
elif [ ${VERBOSE:-0} -eq 1 -a ${QUIET:-0} -ne 1 ];then
	    OUT="VERBOSE"
elif [ ${VERBOSE:-0} -ne 1 -a ${QUIET:-0} -eq 1 ];then
	    OUT="QUIET"
else
	    OUT="SHORT"
fi
}

if [ $# -eq 0 ];then
 	usage
fi
while getopts ":hvqs:c:" OPT ;do
      case "$OPT" in
      "c")
	        if [ $# -eq 1 ];then help ;fi
	    	CATEGORY=$OPTARG
		    #transmit last option to set_out()
		    set_out $3
    	    search $OUT $OPT $CATEGORY
	    	;;
      "q")  
            if [ $# -eq 1 ];then help ;fi
		    QUIET="1"
        	;;
      "s")
            if [ $# -eq 1 ];then help ;fi
       		STRING=$OPTARG
		    #transmit last option to set_out()
		    set_out $3
        	search $OUT $OPT $STRING
        	;;
      "v")
            if [ $# -eq 1 ];then help ;fi
		    VERBOSE="1"
        	;;
      *)
        help ;;
      esac
done  


syntax highlighted by Code2HTML, v. 0.9.1