#!/bin/csh
# grope [-sv]
# options: -s = silent, -v = verbose
# This script gropes for web servers. A possible application might be the
# keeping alive of a dial-up connection. If the ISP has to keep a record of all
# the internet connection details, this might put an additional load on them.
# Tough shit.
#
# for this script to work, we need dd, echo, od, wc, ping, and curl.
#
# drz 20071122

#silent prevents all output
set silent = 0;
#chatty shows all diagnostic messages from ping and curl
set chatty = 0;
#if neither chatty nor silent, grope writes a dot for each ping (progress bar)
set args = `getopt sv $*`
@ iarg = $#args - 1
set errcode = $?
#
while ( $iarg > 0 )
  if ( "$args[$iarg]" =~ *v ) then
    set chatty = 1
  endif
  if ( "$args[$iarg]" =~ *s ) then
    set silent = 1
  endif
  @ iarg--
end

#for the progress bar
set dot="."
set hxc=( 0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z \$ @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z )
set hxl=${#hxc}
set lnl=`tput cols`; set lml=$lnl; @ lml--
@ i = 0
@ j = 0
@ k = 1

# number of bytes in address - ping does not yet (?) support IPv6
set nb_in_adr = 4
#number of bytes we read from /dev/random
@ nb_fr_rnd = $nb_in_adr + $nb_in_adr
#scratch file name
set dot_junk = ".junk"

# do forever
while 1
#retrieve 8 bytes from random device and write into a scratch file
# if ( $chatty != 0 ) then
#   dd if=/dev/random of=$dot_junk ibs=$nb_fr_rnd count=1
# else
    dd if=/dev/random of=$dot_junk ibs=$nb_fr_rnd count=1 >& /dev/null
# endif
#have od convert them to 4 decimals	
  set the_ints = `od -d $dot_junk`
#first one is file offset - skip
  shift the_ints

#how many are left ? we need at least $nb_in_adr
  @ ix = $nb_in_adr
  if ( $#the_ints > $ix ) then
#the 4 components of an IP address are bytes
    while ( $ix > 0 )
      @ the_ints[$ix] = $the_ints[$ix] % 256
      @ ix--
    end
#cobble together the IP address
    set ia = $the_ints[$nb_in_adr]
    @ ix = $nb_in_adr - 1
    while ( $ix > 0 )
      set ia = ${ia}.$the_ints[$ix]
      @ ix--
    end
#anybody there?
    if ( $chatty != 0 ) then
      ping -t 5 -c 1 $ia 
      set pstat = $status
    else
      ping -t 5 -c 1 $ia >& /dev/null
      set pstat = $status
    endif

#need pstat because "if" result masks $status from ping
    if ( $pstat == 0 ) then
#it's a valid address
      if ( ( $chatty == 0 ) && ( $silent == 0 ) ) then
	if ( $j != 0 ) then
#break progress bar
	  echo
	endif
      endif
#Let's see if it is a web server
      if ( $chatty != 0 ) then
#reverse DNS lookup
	host $ia
	curl -f --connect-timeout 5 -m 30 -o /dev/null ${ia}/
	set cstat = $status
      else
	host $ia >& /dev/null
	curl -f --connect-timeout 5 -m 30 -o /dev/null ${ia}/ >& /dev/null
	set cstat = $status
      endif
#init progress bar
      if ( ( $chatty == 0 ) && ( $silent == 0 ) ) then
	@ j = `echo -n $ia | wc -c`
	if ( $cstat == 0 ) then
	  echo -n '*'
	  @ j++
	endif
	@ i = $j
	echo -n $ia
      else
	@ j = 0
	@ i = 0
      endif
      @ k = 1
    else
#ping was unsuccessful
      if ( ( $chatty == 0 ) && ( $silent == 0 ) ) then
#everything below is just eye candy
	@ i++
	@ j++
#make the lines distinct
	if ( $i < $lml ) then
#almost always
	  set chr=$dot
	else
#where does the tag go?
	  @ i = 0
	  if ( $k > $hxl ) then
	    @ k = 1
	  endif
	  set chr="${hxc[$k]}"
	endif
	if ( $j < $lnl ) then
#continue the line
	  echo -n $chr
	else
	  @ j = 0
	  set lnl=`tput cols`; set lml=$lnl; @ lml--
#when 80 lines are written, increment tag character
	  if ( $i == 0 ) then
	    @ k++
	    set chr="${hxc[$k]}"
	  endif
#new line
	  echo $chr
	endif
	unset chr
      endif
    endif
  endif
end

exit

