1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
|
#!/bin/sh
# the next line restarts using tclsh \
exec wish owsim.tcl "$@"
###########################################################
###########################################################
########## Enough of notebook, lets do Simulant! ##########
###########################################################
###########################################################
###########################################################
########## Server Process tcp handler #####################
###########################################################
#enum msg_classification {
# msg_error,
# msg_nop,
# msg_read,
# msg_write,
# msg_dir,
# msg_size, // No longer used, leave here to compatibility
# msg_presence,
#} ;
proc Handler { sock } {
global serve
switch $serve($sock.type) {
0 {
AddLog " Error\n" read
set resp [ServerNone $sock]
}
1 {
AddLog " NOP\n" read
set resp [ServerNone $sock]
}
2 {
AddLog " Read [string range $serve($sock.string) 24 end-1]\n" read
set resp [ServerRead $sock]
}
3 {
AddLog " Write [string range $serve($sock.string) 24 [expr [string length $serve($sock.string)] - $serve($sock.size) - 1] ]\n" read
set resp [ServerWrite $sock]
}
4 {
AddLog " Dir [string range $serve($sock.string) 24 end-1]\n" read
set resp [ServerDir $sock]
}
5 {
AddLog " Size\n" read
set resp [ServerNone $sock]
}
6 {
AddLog " Present [string range $serve($sock.string) 24 end-1]\n" read
set resp [ServerPresent $sock]
}
default {
AddLog " Unrecognized\n" read
set resp [ServerNone $sock]
}
}
foreach {ret size offset val} $resp {break}
AddLog " Respond ret=$ret val=$val\n" write
puts -nonewline $sock [binary format IIIIIIa* $serve($sock.version) [string length $val] $ret $serve($sock.sg) $size $offset $val]
}
#/* message to client */
#struct client_msg {
# int32_t version ;
# int32_t payload ;
# int32_t ret ;
# int32_t sg ;
# int32_t size ;
# int32_t offset ;
#} ;
proc ServerNone { sock } {
return [list 0 0 0 ""]
}
proc ServerRead { sock } {
global serve
global chip
foreach {ret typ alarm dev fil ext} [ParsePath [string range $serve($sock.string) 24 end] $sock] {break}
#puts "ret=<$ret> typ=<$typ> alarm=<$alarm> dev=<$dev> fil=<$fil> ext=<$ext>"
# parse
if { $ret != 0 } { return [list $ret 0 0 ""] }
# is file?
if { $typ ne f } { return [list $serve(EISDIR) 0 0 ""] }
set addr $chip($dev)
# make sure variable defined
if { ![info exist chip($addr.$fil)] } { return [list $serve(ENOENT) 0 0 ""] }
set v [string range $chip($addr.$fil) $serve($sock.offset) end]
set vl [string length $v]
# check return length
if { $vl > $serve($sock.size) } { return [list $serve(EMSGSIZE) 0 0 ""] }
# return value
return [list $vl $vl $serve($sock.offset) $v]
}
proc ServerWrite { sock } {
global serve
global chip
foreach {ret typ alarm dev fil ext} [ParsePath [string range $serve($sock.string) 24 end-[expr $serve($sock.size) + 1]] $sock] {break}
#puts "ret=$ret typ=$typ alarm=$alarm dev=$dev fil=$fil ext=$ext"
# parse
if { $ret != 0 } { return [list $ret 0 0 ""] }
# is file?
if { ![string equal $typ f] } { return [list $serve(EISDIR) 0 0 ""] }
set addr $chip($dev)
# make sure variable defined
if { ![info exist chip($addr.$fil)] } { return [list $serve(ENOENT) 0 0 ""] }
set v [string range $serve($sock.string) end-[expr $serve($sock.size) - 1 ] end ]
if { [catch {set chip($addr.$fil) $v}] } {
set v [string trim $v \00 ]
set chip($addr.$fil) $v
}
return [list [string length $v] [string length $v] 0 ""]
}
# . error code
# type r/d/f/s (root dev file subdir)
# alarm 0/1
# device name
# filename
# extension
proc ServerDir { sock } {
global serve
foreach {ret typ alarm dev fil ext} [ParsePath [string range $serve($sock.string) 24 end] $sock] {break}
#puts "ret=<$ret> typ=<$typ> alarm=<$alarm> dev=<$dev> fil=<$fil> ext=<$ext>"
if { $ret != 0 } { return [list $ret 0 0 ""] }
switch $typ {
r { return [RootDir $alarm $sock] }
s { return [SubDir $dev $fil $sock] }
d { return [DevDir $dev $sock] }
f -
default { return [list $serve(ENOTDIR) 0 0 ""] }
}
}
proc RootDir { alarm sock } {
global serve
global devname
global chip
set flags 0
foreach d $devname {
set addr $chip($d)
# device "present"?
if { [info exist chip($addr.present)] } {
if { !$chip($addr.present) } {continue}
}
# in alarm state?
if { $alarm } {
if { ![info exist chip($addr.alarm)] } {continue}
if { !$chip($addr.alarm) } {continue}
} elseif { [info exist chip($chip($addr.family).flags)] } {
# process flags
set flags [expr $flags | $chip($chip($addr.family).flags)]
}
set e $d\00
AddLog " Respond $d\n" write
puts -nonewline $sock [binary format {IIIIIIa*} $serve($sock.version) [string length $e] 0 $serve($sock.sg) [string length $e] 0 $e]
}
return [list 0 0 $flags ""]
}
proc DevDir { dev sock } {
global serve
global chip
foreach t [list "" $chip($chip($dev).family)] {
foreach x [list $t.read $t.write] {
if { [info exist chip($x)] } {
foreach y $chip($x) {
lappend d [lindex [split $y "/"] 0]
}
}
}
}
foreach x [lsort -dictionary -unique $d] {
set e $dev/$x\00
AddLog " Respond $dev/$x\n" write
puts -nonewline $sock [binary format {IIIIIIa*} $serve($sock.version) [string length $e] 0 $serve($sock.sg) [string length $e] 0 $e]
}
return [list 0 0 0 ""]
}
proc ServerPresent { sock } {
global serve
foreach {ret typ alarm dev fil ext} [ParsePath [string range $serve($sock.string) 24 end] $sock] {break}
# return value
return [list $ret 0 0 ""]
}
#returns list
# . error code
# type r/d/f/s (root dev file subdir)
# alarm 0/1
# device name
# filename
# extension
proc ParsePath { path sock } {
global serve
global chip
set path [string trimright $path \00]
# remove uncached
regsub -all -nocase "/uncached" $path "/" path
# remove "bus.0"
regsub -nocase {/bus\.0} $path "/" path
# flag and remove alarm
set alarm [regexp -nocase {/alarm} $path]
regsub -all -nocase "/alarm" $path "/" path
# remove leading "/" and check for root directory
set path [string range $path 1 end]
if { [string length $path] == 0 } {return [list 0 r $alarm "" "" 0]}
# tease out device name
set pathlist [split $path "/"]
# check if exists
if { ![info exist chip([lindex $pathlist 0])] } {return [list $serve(ENOENT) d $alarm [lindex $pathlist 0] "" 0]}
# real name
set addr $chip([lindex $pathlist 0])
# flip screen
set serve(selected) $addr
# check if present
if { !$chip($addr.present) } {return [list $serve(ENOENT) d $alarm [lindex $pathlist 0] "" 0]}
# just a device?
if { [llength $pathlist] == 1 } {return [list 0 d $alarm $addr "" 0]}
# tease out file and extension (extension=0 of none)
foreach {file ext} [split [join [lrange $pathlist 1 end] "/"]. "."] {break}
# make sure file exists in read or write lists
foreach x [list $addr.read $addr.write] {
if { [lsearch $chip($x) $file] > -1 } {
return [list 0 f $alarm $addr $file $ext]
}
}
# found no valid file
return [list $serve(ENOENT) f $alarm $addr $file $ext]
}
|