#!/bin/sh
# Tcl sees the next lines as an assignment to variable `kludge'.
# For sh, the two shifts cancel the effect of the set, and then we
# run scotty on this script.

set kludge { $*
    shift
    shift
    if test -f ../scotty ; then
      exec ../scotty -nf $0 $*
    else
      exec scotty -nf $0 $*
    fi
}

##
## Emulate the wellknown traceroute program. This is a fast version.
## We trace every each step in parallel. Fun, but not as reliable...
##

proc trace {ip max retries} {
    set ttl 1
    set trace_ip ""
    while {$trace_ip != $ip && $ttl < $max} {
	set icmparg ""
	for {set i 0} {$i < $retries} {incr i} {
	    lappend icmparg $ip
	}
	set trace [icmp trace $ttl $icmparg]
	set lastname ""
	puts -nonewline [format "%2d " $ttl]
	foreach one $trace {
	    set trace_ip [lindex $one 0]
	    set trace_time [lindex $one 1]
	    if {[catch {netdb hosts name $trace_ip} name]} {
		if {[catch {dns ptr $trace_ip} name]} {
		    set name $trace_ip
		}
	    }
	    set name [lindex $name 0]
	    if {$trace_time < 0} { 
		set trace_time "    *** ms" 
	    } else {
		set trace_time [format " %6d ms" $trace_time]
		if {$name != $lastname} {
		    puts -nonewline [format "%-42s" $name]
		    set lastname $name
		}
	    }
	    puts -nonewline $trace_time
	}
	puts ""
	incr ttl
    }
}

proc usage {} {
    puts stderr {usage: traceroute [-m max_ttl] [-w time] hostname}
    exit
}

##
## Parse the command line options.
##

set retries 3
set maxttl 32

if {$argc==0} usage

while {$argv!=""} {
    set argc [llength $argv]
    switch -- [lindex $argv 0] {
	{-m} {
	    if {$argc == 1} usage
	    set maxttl [lindex $argv 1]
	    set argv [lrange $argv 2 end]
	}
	{-w} {
	    if {$argc == 1} usage
	    icmp -timeout [lindex $argv 1]
	    set argv [lrange $argv 2 end]
	}
	{default} break
    }
}

if {[llength $argv] != 1} { usage } else {
    set ip $argv
    if {![regexp "^\[0-9\]+\.\[0-9\]+\.\[0-9\]+\.\[0-9\]+$" $ip]} {
	if {[catch {netdb hosts address $ip} ip]} {
	    if {[catch {dns a $ip}]} {
		puts stderr "traceroute: $ip"
		exit
	    }
	}
    }
    trace [lindex $ip 0] $maxttl $retries
}

exit
