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

set retries 3
set maxttl 30

proc trace {ip} {
    global retries maxttl
    set ttl 1
    set trace_ip ""
    while {"$trace_ip"!="$ip"} {
	set icmparg ""
	for {set i 0} {$i<$retries} {incr i} {
	    lappend icmparg $ip
	}
	set trace [eval icmp -trace $ttl $icmparg]
	set lastname ""
	foreach one $trace {
	    set trace_ip [lindex $one 0]
	    set trace_time [lindex $one 1]
	    if {[catch {nslook $trace_ip} name]} {
		set name $trace_ip
	    }
	    set name [lindex $name 0]
	    if {$trace_time<0} { 
		set trace_time " * * * " 
	    } else {
		set trace_time [format "%6d " $trace_time]
		if {$name!=$lastname} {
		    puts -nonewline [format "%-20s" $name]
		    set lastname $name
		}
	    }
	    puts -nonewline $trace_time
	}
	puts ""
	incr ttl
	if {$ttl>$maxttl} break;
    }
}

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

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

if {$argc==0} usage

while {$argv!=""} {
    set argc [llength $argv]
    case [lindex $argv 0] in {
	{-m} {
	    if {$argc == 1} usage
	    set maxttl [lindex $argv 1]
	    set argv [lrange $argv 2 end]
	}
	{-w} {
	    if {$argc == 1} usage
	    icmp -timeoute [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]} {
	set ip [string trim [nslook $ip]]
    }
    trace $ip 
}
