ASPN ActiveState Programmer Network  
ActiveState, a division of Sophos
/ Home / Perl / PHP / Python / Tcl / XSLT /
/ Safari / My ASPN /
Cookbooks | Documentation | Mailing Lists | Modules | News Feeds | Products | User Groups
Submit Recipe
My Recipes

All Recipes
All Cookbooks


View by Category

Title: Scripted Telnet Client Class
Submitter: Flavio Salgueiro (other recipes)
Last Updated: 2006/09/12
Version no: 1.1
Category: Network resources

 

Not Rated yet


Description:

A simlpe Telnet Client Class utilizing Todd Martin's telnet package available at http://www.tmartin.org/tcltelnet .

Source: Text Source

package require Itcl 3.3
package require telnet 2.0.0

itcl::class TelnetClient {
    public variable host ""
    public variable port 23
    public variable user "admin"
    public variable password "password"
    public variable timeout 10
    public variable debug 0
    private variable my_sock ""

    private variable out_buffer ""
    public variable xwait ""
    common xtimeout 
    
    constructor {args} {}
    destructor {
        disconnect
    }
    
    public method connect {args}
    public method send {args}
    public method disconnect {}
    private method get_data {}
    private method wait_complete {}
    private method timeout {}
    private method reset_timeout {}
    private method wait_or_timeout {}
}

# Lowercase access procedure
proc telnetclient {args} {
    uplevel ::TelnetClient $args
}

itcl::body TelnetClient::constructor {args} {
    eval configure $args
    
    if {($ip == "") || ($port == "")} {
        error "IP and Port must be specified"
    }
}

itcl::body TelnetClient::connect {args} {
    if {![catch {telnet::open $host $port} conn]} {
        set my_sock $conn
        fconfigure $my_sock -blocking false -buffering none -translation auto -eofchar {}
        flush $my_sock
        fileevent $my_sock readable [itcl::code $this get_data]
        wait_or_timeout
        if {[regexp -nocase {(username|login|user)\s?:} $out_buffer]} {
            set login [send "$user"]
            if {[regexp -nocase {(password)\s?:} $login]} {
                set passdRes [send "$password"]
                if {[regexp {(.>)} $passdRes]} {
                    return 0
                } else {
                    close $conn
                    error "Error: Unexpected System Prompt"
                }
            } else {
                close $conn
                error "Error: Unexpectd Password Prompt"
            }
        } else {
            close $conn
            error "Error: Unexpected Login Prompt"
        }
        
    } else {
        error "Error: Connection Refused"
    }
}

itcl::body TelnetClient::get_data {} {
    if {[eof $my_sock]} {
        close $my_sock
        set connected 0
    } else {
        if {![catch {telnet::read  $my_sock} data]} {
            switch -regexp $data {
                # Add login and password patterns as needed
                {([Uu]sername|[Ll]ogin|[Pp]assword)\s?:} {
                    append out_buffer $data
                    wait_complete
                    return
                }
                # Change this value to your Telnet Prompt
                {.>} {
                    append out_buffer $data
                    wait_complete
                    return
                }
                default {
                    append out_buffer $data
                    reset_timeout
                }
            }
        } else {
            wait_complete
            close $mySocked
            return
        }
    }
}

itcl::body TelnetClient::timeout {} {
    catch {after cancel $xwait}
    set xtimeout($this) 1
    puts "Timeout of after [expr {$timeout * 1000}] seconds"
    return
}

itcl::body TelnetClient::wait_or_timeout {} {
    set xwait [after [expr {$timeout * 1000}] [itcl::code $this timeout]]
    vwait [itcl::scope xtimeout($this)]
    return
}

itcl::body tti::TelnetClient::reset_timeout {} {
    catch {after cancel $xwait}
    set xwait [after [expr {$timeout * 1000}] [itcl::code $this timeout]]
    return
}
itcl::body TelnetClient::wait_complete {} {
    catch {after cancel $xwait} wres
    set xtimeout($this) 1
    return
}

itcl::body TelnetClient::send {data} {
    
    set out_buffer ""
    if {![eof $my_sock]} {
        if {![catch {telnet::write $my_sock "$data\r"} err]} {
            flush $my_sock
            fileevent $my_sock readable [itcl::code $this get_data]
            wait_or_timeout
            return $out_buffer
        } else {
            error "$err"
        }
    } else {
        error "Error: Connection Closed"
    }

}

itcl::body TelnetClient::disconnect {} {
    catch { close $my_sock }
}

The license for this recipe is available here.

Discussion:

Useful when wrapping an existing client with Expect is too slow or not convinient due to the limitations with Expect and 64 bit apps in Windows.

To use the client create a telnet client object:

set tn1 [telnetclient #auto -host 192.168.165.100 -user user -password password]

Open the conncetion to the telnet server
$tn1 connect

Send a command to to be executed. The result of the command is returned or an error.

set commandResult [$tn1 send "systeminfo"]

Close the connection to the telnet server
$tn1 disconnect



Add comment

Number of comments: 1

Should this recipe work as is?, Rich Kaminski, 2007/01/31
I would like to use this code, but I can not get it to work. I notice the value of "$data" is empty when telneting to the windows xp machine and then the script closes the telnet session. Any thoughts?
Add comment



Highest rated recipes:

1. A minimal debugger

2. Socket based communicatio...

3. With busy cursor

4. Multi-character split

5. LCD Number Display

6. Supporting mouse wheel ...

7. Get widget info

8. Check creditcard numbers ...

9. WSCP - showServerStatus

10. Inline GIF image into ...




Privacy Policy | Email Opt-out | Feedback | Syndication
© 2006 ActiveState Software Inc. All rights reserved.