Posted to tcl by patthoyts at Mon May 15 21:25:04 GMT 2006view pretty
# cmdloop.tcl - Copyright (C) 2005 Pat Thoyts <patthoyts@users.sourceforge.net> # # $Id: cmdloop.tcl,v 1.2 2006/04/16 20:16:36 pat Exp $ namespace eval ::cmdloop { variable hosts_allow if {![info exists hosts_allow]} { set hosts_allow {127.0.0.1 ::1 82.33.96.128} } variable welcome if {![info exists welcome]} { set welcome "Hello %client %port" } variable cmds_deny if {![info exists cmds_deny]} { set cmds_deny {exit denied} } } # cmdloop::Read -- # # Reads commands from stdin and evaluates them. This permits # us to issue commands to the server while it is still # running. Suitable commands are ijbridge::presence and # ijbridge::say or ijbridge::xmit. # proc ::cmdloop::Read {chan ochan state} { variable cmds_deny upvar #0 $state input if {![info exists input]} {set input {}} if {[eof $chan]} { puts $ochan "!! EOF $chan" } if {[gets $chan line] != -1} { append input $line if {[string length $input] > 0 && [info complete $input]} { set cmd [lindex $input 0] if {[lsearch -exact $cmds_deny $cmd] != -1} { set res "$cmd command disabled" } elseif {$cmd eq "puts" && [string match "sock*" $chan] \ && [llength $input] == 2} { set res [lindex $input 1] } else { set code [catch {uplevel \#0 $input} res] } unset input puts $ochan $res } } } # cmdloop::Accept -- # # Setup the client channel for reading commands as we do # for stdin. Useful with tkcon's socket connection feature. # proc ::cmdloop::Accept {chan client port} { # we could validate the client here. if {[lsearch $::cmdloop::hosts_allow $client] == -1} { puts $chan "Access denied" close $chan return } fconfigure $chan -blocking 0 -buffering line puts $chan [welcome $client $port] fileevent $chan readable \ [list ::cmdloop::Read $chan $chan ::cmdloop::state_$chan] } proc ::cmdloop::welcome {{client {}} {port {}}} { variable welcome return [string map [list %client $client %port $port] $welcome] } proc ::cmdloop::cmdloop {} { variable welcome puts [welcome] puts -nonewline "> " fconfigure stdin -blocking 0 -buffering line fileevent stdin readable \ [list ::cmdloop::Read stdin stdout ::cmdloop::state_stdin] } proc ::cmdloop::listen {{myaddr 0.0.0.0} {port 5441}} { variable Socket if {$port ne {}} { set Socket [socket -server ::cmdloop::Accept -myaddr $myaddr $port] } } # Local variables: # mode: tcl # End: