1: #!/usr/bin/tcl 2: # Enable debugging? (generally a bad idea) 3: set DEBUG 0 4: 5: # What port should be used as the control port (must be the same as the 6: # rdatapipe server)? 7: set controlport 4500 8: 9: 10: 11: 12: 13: ########################################################################### 14: ########################################################################### 15: ########################################################################### 16: # This is my mess. ######################################################## 17: ########################################################################### 18: 19: 20: 21: set host [lindex $argv 0] 22: if {$host==""} { puts "Usage:\n\t$argv0 <host>"; exit } 23: 24: 25: if {!$DEBUG} { 26: if {[fork]!=0} { exit 1 } 27: } 28: 29: 30: proc datapipe {src dest} { 31: global perm DEBUG 32: fconfigure $src -blocking 0 -translation binary 33: fconfigure $dest -translation binary 34: set check 0 35: set ln "" 36: catch { set ln [read $src] } 37: puts -nonewline $dest $ln 38: flush $dest 39: if {$DEBUG} { puts -nonewline "$ln"; flush stdout } 40: if {([eof $src] || [eof $dest])} { 41: if {$DEBUG} { puts "\[$src , $dest\] Dead" } 42: catch { close $src } 43: catch { close $dest } 44: set perm 1 45: } 46: } 47: 48: proc HandleCommand {sock} { 49: global forever host DEBUG 50: gets $sock ln 51: set cmd [lindex $ln 0] 52: set arg [lrange $ln 1 end] 53: switch -- $cmd { 54: "datapipe" { 55: if {[fork]!=0} { wait; return } 56: if {[fork]!=0} { exit } 57: set SelfPort [lindex $arg 0] 58: set DestPort [lindex $arg 1] 59: set RemtHost [lindex $arg 2] 60: set DestHost [lindex $arg 3] 61: if {$DestHost==""} { set DestHost $host } 62: if {$RemtHost==""} { set RemtHost 127.0.0.1 } 63: catch { 64: set selfId [socket $RemtHost $SelfPort] 65: fconfigure $selfId -blocking 0 66: set destId [socket $DestHost $DestPort] 67: fconfigure $destId -blocking 0 68: 69: } 70: if {![info exists selfId] || ![info exists destId]} { 71: if {$DEBUG} { puts "Connection failed." } 72: catch { close $selfId } 73: catch { close $destId } 74: exit 75: } 76: if {$DEBUG} { puts "\[$selfId , $destId\] Connection completed." } 77: fileevent $selfId readable "datapipe $selfId $destId" 78: fileevent $destId readable "datapipe $destId $selfId" 79: flush $destId 80: vwait perm 81: exit 82: } 83: "keepalive" { 84: if {$DEBUG} { puts "Recieved keepalive [clock seconds]" } 85: } 86: default { 87: if {$DEBUG && $cmd!=""} { puts "Unknown command: $cmd -- $arg" } 88: } 89: } 90: if {[eof $sock]} { set forever 1 } 91: } 92: 93: proc bgerror {error} { puts "Error: $error"; return } 94: 95: while {1} { 96: set sockId "" 97: catch { set sockId [socket $host $controlport] } 98: if {$sockId!=""} { 99: fconfigure $sockId -blocking 0 100: fileevent $sockId readable "HandleCommand $sockId" 101: vwait forever 102: close $sockId 103: } else { 104: sleep 30 105: } 106: } rdatapiped.tcl is the server (firewalled) side of rdatapipe. |