#!/bin/sh
# the next line restarts using scotty -*- tcl -*- \
exec scotty "$0" "$@"

package require Tnm 2.1

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

proc trace {dst {max 32} {retries 3}} {
    for {set i 0} {$i < $retries} {incr i} { 
	lappend icmparg $dst 
    }
    set ip ""
    for {set ttl 1} {$ip != $dst && $ttl < $max} {incr ttl} {
	set trace [icmp -retries 0 trace $ttl $icmparg]
	set names ""
	set time ""
	foreach {ip rtt} [join $trace] {
	    if {[catch {netdb hosts name $ip} name]} {
                if {[catch {dns name $ip} name]} {
                    set name $ip
                }
            }
	    if {[lsearch $names $name] < 0 && $name != "0.0.0.0"} {
		lappend names $name
	    }
	    if {$rtt < 0} {
		append time "    *** ms"
	    } else {
		append time [format " %6d ms" $rtt]
	    }
	}
	puts [format "%2d %-44s %s" $ttl $names $time]
    }
}

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 dst $argv
    if {![regexp {^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$} $dst]} {
	if {[catch {netdb hosts address $dst} dst]} {
	    if {[catch {dns address $dst}]} {
		puts stderr "traceroute: $dst"
		exit
	    }
	}
    }
    trace [lindex $dst 0] $maxttl $retries
}

exit
