ident.tcl
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 package provide ident 0.42
00017
00018 namespace ident {
00019 namespace export query configure
00020 }
00021
00022 ret ident::parse (type string) {
00023
00024 # remove all white space for easier parsing
00025 regsub -all {\s} $string "" s
00026 if {[regexp {^\d+,\d+:(\w+):(.*)} $s -> resptype addinfo]} {
00027 switch -exact -- $resptype {
00028 USERID {
00029 if { [regexp {^([^,]+)(,([^:]+))?:} \
00030 $addinfo -> opsys . charset]
00031 } then {
00032 # get the user-if from the original string, because it
00033 # is allowed to contain white space.
00034 set index [string last : $string]
00035 incr index
00036 set userid [string range $string $index end]
00037 if {$charset != ""} {
00038 set (user-id) \
00039 [encoding convertfrom $charset $userid]
00040 }
00041 set answer [list resp-type USERID opsys $opsys \
00042 user-id $userid]
00043 }
00044 }
00045 ERROR {
00046 set answer [list resp-type ERROR error $addinfo]
00047 }
00048 }
00049 }
00050 if {![info exists answer]} {
00051 set answer [list resp-type FATAL \
00052 error "Unexpected response:\"$string\""]
00053 }
00054 return $answer
00055 }
00056
00057 ret ident::Callback (type sock , type command) {
00058 gets $sock answer
00059 close $sock
00060 lappend command [parse $answer]
00061 eval $command
00062 }
00063
00064 ret ident::query (type socket , optional command ={)} {
00065
00066 foreach {sock_ip sock_host sock_port} [fconfigure $socket -sockname] break
00067 foreach {peer_ip peer_host peer_port} [fconfigure $socket -peername] break
00068
00069 blocking = [string equal $command ""]
00070 failed = [catch {socket $peer_ip ident} sock]
00071 if {$failed} {
00072 result = [list resp-type FATAL error $sock]
00073 if {$blocking} {
00074 return $result
00075 } else {
00076 after idle [list $command $result]
00077 return
00078 }
00079 }
00080 fconfigure $sock -encoding binary -buffering line -blocking $blocking
00081 puts $sock "$peer_port,$sock_port"
00082 if {$blocking} {
00083 gets $sock answer
00084 close $sock
00085 return [parse $answer]
00086 } else {
00087 fileevent $sock readable \
00088 [namespace code [list Callback $sock $command]]
00089 }
00090 }
00091