#!/bin/ash
# rustic `file` (by M. Andreoli)
# [ with dd and hexd 
# (5/11/00 tweaked by A. Costa)

#Syntax

opt=$1

case Z$opt in
    Z-d) set -x;shift ;;	 # debug mode...
    Z-h|Z) echo "Usage (mu-file): file [files]" ; exit ;;
    *)
esac


# Functions

FetchString()		# filename offset count
{			# returns:  string
    dd if="$1" skip=$2 bs=1c count=$3 2>/dev/null
}


# compare a text string with a part of a file
TestString() 		# filename offset count string
{			# returns:  errorcode
    f="$1"	offset=$2	n=$3	string1="$4" 

    string2="`dd if="$f" skip=$offset bs=1c count=$n 2>/dev/null`"
    test "$string1" = "$string2"
}


# compare a hex text string with a part of a file hex string
TestHex()		# filename offset count hexstring
{			# returns:  errorcode
    f="$1"	offset=$2	n=$3	string1=$4

    string2="`dd if="$f" skip=$offset bs=1c count=$n 2>/dev/null | hexd -x`"
    test $string1 = $string2
}


DescribeFile()		# filename file_description
{			# returns: string, + continues...
    f="$1"	message="$2"
    echo "$f"": $message"
    continue
}


ShowTestHex()		# prompt filename startaddr count hexstring
{			# returns: string + continues, if true, or else nothing
    message="$1"	f="$2"	offset=$3	n=$4	string=$5

    if TestHex "$f" $offset $n $string
    then
	DescribeFile $f "$message"
    fi
}
 

ShowTestString() 	# prompt filename offset startaddr string
{			# returns: string + continues, if true, or else nothing
    message="$1"	f="$2"	offset=$3	n=$4	string1="$5"

    if TestString "$f" $offset $n "$string1"
    then
	DescribeFile $f "$message"
    fi
}


# main loop
for f in "$@"
do
    # special
    [ -d "$f" ]   && DescribeFile "$f" "directory"
    [ -L "$f" ]   && DescribeFile "$f" "symbolic link"
    [ ! -f "$f" ] && DescribeFile "$f" "not existent"

    # script

    # check for text in the first $len chars
    len=12
    s0_to_len="`FetchString $f 0 $len | hexd -t`"

    case $s0_to_len in
     \#!/bin/sh*)	DescribeFile "$f" "Bourne shell script text" ;;
     \#!/bin/ash*)	DescribeFile "$f" "ash script text" ;;
     \#!/bin/bash*)	DescribeFile "$f" "Bash shell script text" ;;
     \#!/bin/csh*)	DescribeFile "$f" "C shell script text" ;;
     \#!/bin/ksh*)	DescribeFile "$f" "Korn shell script text" ;;
     \#!/bin/perl*)	DescribeFile "$f" "perl command text" ;;
     \#!/bin/*)		DescribeFile "$f" "script text" ;;
      ?ELF*)		DescribeFile "$f" "ELF executable" ;;
      BZ*)		DescribeFile "$f" "bzip compressed data" ;;
      PK*)		DescribeFile "$f" "Zip archive data" ;;
      Rar!*)		DescribeFile "$f" "RAR archive data" ;;
      %PDF-*)		DescribeFile "$f" "PDF document" ;;
      %!*)		DescribeFile "$f" "PostScript document text" ;;
      GIF8*)		DescribeFile "$f" "GIF image data" ;;
      ?PNG*)		DescribeFile "$f" "PNG image data" ;;
      BM*)		DescribeFile "$f" "PC bitmap data" ;;
      MZ*)		DescribeFile "$f" "MS-DOS executable (EXE)" ;;
      HPHP48-*)		DescribeFile "$f" "HP48 binary" ;;
      %%HP:*)		DescribeFile "$f" "HP48 text" ;;
      MThd*)		DescribeFile "$f" "Standard MIDI data" ;;
      RIFF????WAVE)	DescribeFile "$f" "Microsoft RIFF, WAVE audio data" ;;
      RIFF*)		DescribeFile "$f" "Microsoft RIFF" ;;
      MM?\**)		ShowTestHex "TIFF image data, big-endian"    "$f" 2 00 ;;
      II\**)		ShowTestHex "TIFF image data, little-endian" "$f" 3 00 ;;
    esac

    # check for hex in the first $len chars
    len=3
    s0_to_len_hex="`FetchString $f 0 $len | hexd -x`"

    case $s0_to_len_hex in
      1f8b*) DescribeFile "$f" "gzip compress data" ;;
      f702*) DescribeFile "$f" "TeX DVI file" ;;
      ffd8*) DescribeFile "$f" "JPEG image data" ;;
    esac
    
    # Linux 
    ShowTestString "Linux/i386 ext2 filesystem [probable :(]" "$f" 1080 1 'S'
    ShowTestString "Linux/i386 swap file" "$f" 4086 10 'SWAP-SPACE'

    # compressed
    ShowTestString "TAR archive" "$f" 257 5 ustar

    # default
    echo "$f: ASCII text or data"
done
