#!/bin/sh
#
# Nico Schottelius <nico-linux@schottelius.org>
# URL: http://creme.schottelius.org/~nico/schwanz3/
# Date: 10-Oct-2004
# Last Modified: ls -l or git
# Copying: GPL
# 
# Calculates your personal penis size
# 
# Please send modifications and new checks in 'diff -u' format to me.

################################################################################
# list of checks - put every check herein
################################################################################
ALL_CHECKS="ck_root ck_users ck_home ck_crypto ck_uptime"
ALL_CHECKS="$ALL_CHECKS ck_cpucount ck_ram ck_swap ck_mail"
ALL_CHECKS="$ALL_CHECKS ck_mp3 ck_good_music ck_traffic ck_dot_files"
ALL_CHECKS="$ALL_CHECKS ck_iface"

################################################################################
# list of ENABLED checks - filter out some extremly subjective ones
################################################################################
ENABLED_CHECKS="$(echo $ALL_CHECKS | sed 's/ck_dot_files//')"

# which checks to enable?
CHECKS=$ENABLED_CHECKS
#CHECKS="ck_traffic"
#CHECKS="$ALL_CHECKS"

################################################################################
# get argv
################################################################################

banner()
{
   echo "*** schwanz3-rc10 ***"
   echo ""
   echo "   Your personal penis size calculator"
   echo ""
}

footer()
{
   echo ""
   echo "Get the latest version at http://creme.schottelius.org/~nico/schwanz3/"
}

usage()
{
   banner
   echo "   -s|--silent:   Only print result"
   echo "   -l|--list:     List available checks"
   echo "   -e|--enabled:  List enabled checks"
   echo "   -t|--tests:    Select tests to use (-t must be the last parameter)"
   echo "   -h|--help:     This help"
   footer
   exit 0
}

# normally print output
ECHO="echo"
RECHO="echo"

while [ $# -gt 0 ]; do
   case $1 in
      -s|--silent|--silentgrow)
         # only print the result (RESULTECHO)
         ECHO="true"
         RECHO="echo"
         SILENT=yes
         ;;
      -t|--tests)
         if [ $# -lt 2 ]; then
            banner
            echo "Please specify which tests to use."
            exit 1
         fi
         shift; CHECKS="$@"
         TMP_CHECKS=$CHECKS

         # remove $@, set $# = 1
         # the following does not work on posix :(
         # shift $(($#-1))

         # so we use expr
         shift $(expr $# - 1)
         
         for test_check in $ALL_CHECKS; do
            TMP_CHECKS=$(echo $TMP_CHECKS| sed "s/$test_check//")
         done
         
         if [ "$TMP_CHECKS" ]; then
            banner
            echo "/****> There are some unknown tests specified:"
            for check in $TMP_CHECKS; do
               echo "|-> $check"
            done
            echo "\****> eof."
            exit 1
         fi
         ;;
      -e|--enabled)
         banner
         echo "/****> The following checks are enabled by default: "
         for check in $ENABLED_CHECKS; do
            echo "|-> $check"
         done
         echo "\****> eof."
         exit 0
         ;;
      -l|--list)
         banner
         echo "/****> The following checks are available: "
         for check in $ALL_CHECKS; do
            echo "|-> $check"
         done
         echo "\****> eof."
         exit 0
         ;;
      *) usage
         ;;
    esac
    shift
done
   

################################################################################
# below are the checks
################################################################################

################################################################################
# check mail stats
#
# 1000 Mails = 1cm
#
ck_mail()
{

   $ECHO "*-> Checking your Mails in $MAIL ..."

   #
   # check whether $MAIL points to a maildir or mbox
   #
   if [ -d "${MAIL}" ]; then
      # How many mails do you have? (count)
      MAIL_COUNT=$(find "$MAIL" -type f 2>/dev/null | wc -l)
      
      # How much size does your Maildir use? (in KiBiByte)
      MAIL_SIZE=$(du -s "$MAIL" | cut -f 1)
   elif [ -f "${MAIL}" ]; then
      MAIL_COUNT=$(grep "^From " "$MAIL" | wc -l)
      MAIL_SIZE=$(ls -l "$MAIL" | awk '{ print $5 }')
   else
      MAIL_COUNT=0
      MAIL_SIZE=0
   fi

   #
   # 1 MiB = 1cm
   #
   MAIL_SIZE_FACTOR="1048576"

   #
   # How many mails do make one cm?
   #
   MAIL_COUNT_FACTOR="1000"

   MAIL_COUNT_SIZE=$(echo ${MAIL_COUNT}/${MAIL_COUNT_FACTOR} | bc -l)
   MAIL_SIZE_SIZE=$(echo ${MAIL_SIZE}/${MAIL_SIZE_FACTOR} | bc -l)

   $ECHO "|-> Found $MAIL_COUNT mails, which use $MAIL_SIZE KiBiBytes."

   SIZE=$(echo $SIZE + $MAIL_COUNT_SIZE + $MAIL_SIZE_SIZE | bc -l)
}

################################################################################
# root (uid0)
# you are root? root should not run us! - 1000 cm.
ck_root()
{
   $ECHO "*-> Checking for the being of root ..."
   [ "$USER" = "root" ] && SIZE=$(echo $SIZE - 10000 | bc -l)

   $ECHO "|-> You are $USER."
}

################################################################################
# usercount
# user/10 = 1cm
ck_users()
{
   $ECHO "*-> Finding users ..."
   USER_COUNT=`cat /etc/passwd | wc -l`

   $ECHO "|-> You have $USER_COUNT user(s)."

   U_SIZE=`echo "$USER_COUNT / 10" | bc -l 2>/dev/null`
   SIZE=`echo $SIZE + $U_SIZE | bc -l 2>/dev/null`
}

################################################################################
# home
ck_home()
{
   $ECHO "*-> Checking size of your home ($HOME)..."
   
   # disk stats (in KB)
   #
   # Warning:
   # - df on Linux has 1k-Blocks
   # - df on SunOS has 512 Byte-Blocks
   # 
   case $(uname -s) in
      SunOS)
         HOME_FULL=$(df -k "$HOME" | tail -1 | awk '{ print $2 }')
         ;;
      *)
         HOME_FULL=$(df -k "$HOME" | tail -n 1 | awk '{ print $2 }')
         ;;
   esac

   $ECHO "|-> Home is of size ${HOME_FULL}."

   # 1GB = 1cm
   HOME_FULL_FACTOR="1048576"
   HOME_FULL_SIZE=`echo ${HOME_FULL}/${HOME_FULL_FACTOR} | bc -l 2>/dev/null`

   SIZE=$(echo $SIZE + $HOME_FULL_SIZE | bc -l 2>/dev/null)

}

################################################################################
# crypto algorithm (/proc/crypto) on a GNU/Linux system
# pro algorithm +=5

ck_crypto()
{
   $ECHO "*-> Searching for crypto algorithm(s) ..."
   
   COUNT=0

   case $(uname -s) in
      Linux)
         COUNT=`grep '^name' /proc/crypto | wc -l 2>/dev/null`
         ;;
   esac

   $ECHO "|-> Found $COUNT crypto algorithms."

   CCOUNT=`echo "$COUNT" '* 5' | bc -l 2>/dev/null`
   SIZE=`echo $SIZE + $CCOUNT | bc -l 2>/dev/null`
}

################################################################################
# cpucount
# cpu_anzahl*10cm

ck_cpucount()
{
   $ECHO "*-> Searching processors ..."

   # zero processors, if none found
   COUNT=0

   case `uname -s` in
      Linux)
      case `uname -m` in
         ppc|i?86|parisc|x86_64) 
            COUNT=$(grep '^processor' /proc/cpuinfo | wc -l)
            ;;
         alpha)
            COUNT=$(grep 'cpus detected' /proc/cpuinfo | sed 's/.*://')
            ;;
         sparc|sparc64)
            COUNT=$(grep 'ncpus probed' /proc/cpuinfo | cut -d: -f2)
            ;;
      esac
      ;;

      NetBSD|FreeBSD|Darwin|OpenBSD)
         COUNT=$(sysctl -n hw.ncpu)
      ;;
   esac

   CCOUNT=`echo "$COUNT" '*' "$COUNT" '* 10' | bc -l 2>/dev/null`
   $ECHO "|-> Found $COUNT processors."

   SIZE=`echo $SIZE + $CCOUNT | bc -l 2>/dev/null`
}


################################################################################
# uptime
# days*days/10 = 1cm

ck_uptime()
{
   $ECHO "*-> Checking uptime ..."
   #DAYS=`uptime| grep day | sed 's/.*up \([0-9]*\) day.*/\1/'`
   DAYS=$(uptime| sed -e '/day/! d' -e '/day/ s/.*up \([0-9]*\) day.*/\1/')

   [ -z "$DAYS" ] && DAYS=0

   $ECHO "|-> Your system is $DAYS day(s) up."
   DCOUNT=`echo "$DAYS * $DAYS / 10" | bc -l 2>/dev/null`

   SIZE=`echo $SIZE + $DCOUNT | bc -l 2>/dev/null`
}

################################################################################
# ram
# 100MiB == 1cm
ck_ram()
{
   $ECHO "*-> Checking RAM ..."

   # unknow do not have RAM. At least not for us.
   # specified in KiBiBytes
   RAM=0

   case `uname -s` in
      Linux)
         RAM=`free | grep '^Mem' | awk '{ print $2 }'`
         ;;
      NetBSD)
         RAM=$(expr "(" $(cat /kern/physmem) "*" $(cat /kern/pagesize) ")" / 1024)
         #RAM=$(expr $(sysctl -n hw.physmem) / 1024)
         ;;
      SunOS)
         RAM_tmp="`prtconf | awk '/Memory size/ { print $3 }'`"
         RAM=$(echo "$RAM_tmp * 1024" | bc -l)
         ;;
   esac
   
   $ECHO "|-> Found $RAM KiBiBytes RAM."

   CRAM=$(echo $RAM / 102400 | bc -l)
   SIZE=$(echo $SIZE + $CRAM | bc -l)
}

################################################################################
# swap
# 1GiB == 1cm
ck_swap()
{
   $ECHO "*-> Checking Swap ..."

   case $(uname -s) in
      Linux)
         SWAP=$(free | awk '/^Swap/ { print $2 }')
         ;;
      NetBSD)
         SWAP=$(expr 0 $(swapctl -lk | awk '/^\// { print "+ " $2 }'))
         ;;
      SunOS)
         SWAP=$(swap -s | awk '{ print $11 }' | sed -e 's/k//')
         ;;
   esac

   $ECHO "|-> Found $SWAP KiBiBytes Swap."

   CSWAP=$(echo "$SWAP / (1024*1024)" | bc -l)

   SIZE=$(echo $SIZE + $CSWAP | bc -l)
}
################################################################################
# check for special dot-files
# mostly ones concerning the security and shells
ck_dot_files()
{
   
   # files
   DOT_FILES="gnupg ssh nessusrc nethackrc dsh zshrc tcsh.config bashrc \
              muttrc procmailrc cvspass ion ion2 ion3"
   # cm to add if found... to be continued
   VALUES="+100 +100 +100 +500 +50 +50 +50 -50 \
           +10 +10 -50 +50 +40 +100"

   $ECHO "*-> Checking special dot-files ..."

   i=0
   for file in $DOT_FILES; do
      i=$(($i+1))
      if [ -e "${HOME}/.${file}" ]; then
         COUNT=`echo $VALUES | cut -f $i -d" "`
         $ECHO "|-> Found $file ($COUNT cm)."
         SIZE="`echo $SIZE $COUNT | bc -l 2>/dev/null`"
      else
         $ECHO "|-> Did not found $file"
      fi
   done
}

################################################################################
# check for mp3s - which are deprecated! Please use oggs!
# every mp3 is minus (-) 5cm
ck_mp3()
{
   $ECHO "*-> Searching MP3s ..."

   COUNT=$(find "$HOME" -name \*.mp3 2>/dev/null | wc -l)
   $ECHO "|-> Found $COUNT MP3s."
   SIZE=`echo $SIZE - $COUNT "* 5" | bc -l`

}
################################################################################
# check for oggs
# every ogg + 5cm
ck_good_music()
{
   $ECHO "*-> Searching music (ogg, flac) ..."

   COUNT=$(find "$HOME" 2>/dev/null | grep -i -e '\.mp3$' -e '\.flac$' | wc -l)
   $ECHO "|-> Found $COUNT files of music in good formats."
   SIZE=`echo $SIZE + $COUNT "* 5" | bc -l`
}

################################################################################
# check x windows, kde, graphic cards
# by obri - STlLL MISSIING


#################################################################################
# Traffic
# 1GiB == 1m
# TODO:
# - find $any_useful_device on $any_unix
# --> needs uname -s as above
# --> needs ifconfig or ip to list devices
# --> needs list of devices for $OS to check
ck_traffic()
{
   $ECHO "*-> Checking Traffic ..."

   TRAFFIC=0

   case $(uname -s) in
      Linux)
         TRAFFIC1=`/sbin/ifconfig eth0| grep 'bytes' | cut -d':' -f2 | cut -d'(' -f1`
         TRAFFIC2=`/sbin/ifconfig eth0| grep 'bytes' | cut -d ':' -f3 | cut -d'(' -f1`
         TRAFFIC=`echo $TRAFFIC1 + $TRAFFIC2 | bc -l 2>/dev/null`
         ;;
      SunOS)
         # FIXME: check if the conversion transferred_pkts * MTU' is valid
         TRAFFIC1=$(netstat -i | grep "$HOSTNAME")
         TRAFFIC=$(echo $TRAFFIC1 | awk '{ print "("$5 " + " $7 ") * " 1500 }' | bc -l)
         ;;
   esac

   $ECHO "|-> $TRAFFIC Bytes transferred."

   CTRAFFIC=`echo "$TRAFFIC / (1024*1024*10.24)" | bc -l 2>/dev/null`

   SIZE=`echo $SIZE + $CTRAFFIC | bc -l 2>/dev/null`
}

################################################################################
# check number and type of interfaces
# by moemoe
ck_iface(){
   case $(uname -s) in
      Linux)
         $ECHO "*-> Checking interfaces (lo excluded)..."
         N_IFACE=$(awk 'END { print NR -3}' /proc/net/dev)
         $ECHO "|-> $N_IFACE interfaces found."
         N_WFACE=$(awk 'END { print NR -2}' /proc/net/wireless)
         $ECHO "|-> $N_WFACE wlan interfaces found."
         SIZE=$(echo "$SIZE + (30 * $N_IFACE + 20 * $N_WFACE)" | bc -l)
      ;;
   esac
}


################################################################################
# CHECKS TODO:

# encrypted home-fs?
# +50

# encrypted swap: swap * swap / 100MiB

# windowing system:
# x,y,fresco,berlin
# x: -20
# y: 0
# fresco: +20
# berlin: +50

# festplattenplatzfrei
# 90% voll -> 9cm+
# 95% voll: -> +9 - 5
# 100% voll: +9 - 10 -> -1


# Hard disk usage
# < 1GB: -5cm
# 1GB - 100GB: 	0.5cm per GB
# 100 - 500GB: 	0.6cm per GB
# 500 - 1TB: 	0.7cm per GB
# 1TB - 5TB:	0.8cm per GB
# 
# Hard disk type:
# 
# 
# CPU power - really?
# 1. Select different Architectures
# 2. Select CPU families
# 3. Select Cache
# 4. Select Mhz
# 5. Select CPU Count

################################################################################
# begin with zero size
SIZE=0

$ECHO "/****> Please wait, measuring the size..."
$ECHO "|=> Using the following tests: $CHECKS"

for check in $CHECKS; do
   old_size=$SIZE
   $check
   [ -z "$SIZE" ] && SIZE=$old_size
   $ECHO "|=> Size grew to ${SIZE} ... please wait ..."
done

[ -z "$SIZE" ] && SIZE=0

if [ "$SILENT" = yes ]; then
   $RECHO "$SIZE"
else
   $RECHO "\****> Your penis is $SIZE cm long."
fi

# display schwanz: every 20cm a '*'
STARS=`echo $SIZE / 20 | bc`
$ECHO -n " \***> "
i=0
echo -n 8
while [ $i -lt $STARS ]; do
   $ECHO -n '='
   true
   i=$(($i+1))
done
$ECHO D

