| 1 | #!/usr/bin/env tclsh |
|---|
| 2 | |
|---|
| 3 | ############################################################################### |
|---|
| 4 | # |
|---|
| 5 | # tolsh.tcl -- |
|---|
| 6 | # |
|---|
| 7 | ############################################################################### |
|---|
| 8 | |
|---|
| 9 | package provide tolsh 1.0 |
|---|
| 10 | |
|---|
| 11 | ############################################################################### |
|---|
| 12 | # |
|---|
| 13 | # Tol_HciWriter -- |
|---|
| 14 | # |
|---|
| 15 | # This file will be invoked by TOL if HCI output is enabled |
|---|
| 16 | # |
|---|
| 17 | ############################################################################### |
|---|
| 18 | proc Tol_HciWriter { msg } { |
|---|
| 19 | puts [string trim $msg] |
|---|
| 20 | } |
|---|
| 21 | |
|---|
| 22 | ############################################################################### |
|---|
| 23 | # |
|---|
| 24 | # namespace tolsh -- encapsulate tolsh functionality |
|---|
| 25 | # |
|---|
| 26 | ############################################################################### |
|---|
| 27 | namespace eval ::tolsh { |
|---|
| 28 | variable options |
|---|
| 29 | |
|---|
| 30 | # By default load initLibrary |
|---|
| 31 | # |
|---|
| 32 | set options(lang) 0 |
|---|
| 33 | set options(initlib) 1 |
|---|
| 34 | set options(iniproject) 1 |
|---|
| 35 | set options(compile) "" |
|---|
| 36 | set options(vmode) "" |
|---|
| 37 | set options(out,enabled) no |
|---|
| 38 | set options(runmode) "" |
|---|
| 39 | set options(tolversion) "" |
|---|
| 40 | } |
|---|
| 41 | |
|---|
| 42 | ############################################################################### |
|---|
| 43 | # |
|---|
| 44 | # getoptions -- process the command line |
|---|
| 45 | # |
|---|
| 46 | # The command line accepted by tolsh is: |
|---|
| 47 | # |
|---|
| 48 | # -i --> do not include initLibrary |
|---|
| 49 | # -np --> do not load _iniproject.tol |
|---|
| 50 | # -c"..." --> compile a tol expression |
|---|
| 51 | # -c "..." --> compile a tol expression |
|---|
| 52 | # -v?A? --> enable all output |
|---|
| 53 | # -vE --> enable error output |
|---|
| 54 | # -vS --> enable system output |
|---|
| 55 | # -vU --> enable user output |
|---|
| 56 | # -vT --> enable trace output |
|---|
| 57 | # -m?A? --> disable all output |
|---|
| 58 | # -mE --> disable error output |
|---|
| 59 | # -mS --> disable system output |
|---|
| 60 | # -mU --> disable user output |
|---|
| 61 | # -mT --> disable trace output |
|---|
| 62 | # -d --> start in dialog mode |
|---|
| 63 | # -e?n? --> use english language |
|---|
| 64 | # -s?p? --> use spanish language |
|---|
| 65 | # -tolversion ver --> specify an strict tol version to start with |
|---|
| 66 | # -server [port] --> start tol as a server tolsvc.<pid>.log will be the log |
|---|
| 67 | # [port] is the port number where the serve will be listening. |
|---|
| 68 | # |
|---|
| 69 | # Any other value will be considered a file to compile |
|---|
| 70 | # |
|---|
| 71 | # Arguments: |
|---|
| 72 | # |
|---|
| 73 | ############################################################################### |
|---|
| 74 | proc ::tolsh::getoptions { cmdline } { |
|---|
| 75 | variable options |
|---|
| 76 | |
|---|
| 77 | logtmp "entering ::tolsh::getoptions $cmdline" |
|---|
| 78 | |
|---|
| 79 | # cmdline could be a bad list so the next sentence could fail. |
|---|
| 80 | # try to test it in front of bugs situations. |
|---|
| 81 | set num [llength $cmdline] |
|---|
| 82 | set delayed_msg "" |
|---|
| 83 | set i 0 |
|---|
| 84 | while {$i < $num} { |
|---|
| 85 | set item [lindex $cmdline $i] |
|---|
| 86 | if {[string index $item 0] eq "-"} { |
|---|
| 87 | set opt [string range $item 1 end] |
|---|
| 88 | if {$opt eq "e" || $opt eq "en"} { |
|---|
| 89 | set $options(lang) 0 |
|---|
| 90 | } elseif {$opt eq "s" || $opt eq "sp"} { |
|---|
| 91 | set $options(lang) 1 |
|---|
| 92 | } elseif {$opt eq "i"} { |
|---|
| 93 | # initLibrary should not be loaded |
|---|
| 94 | # |
|---|
| 95 | set options(initlib) 0 |
|---|
| 96 | } elseif {$opt eq "np"} { |
|---|
| 97 | set $options(iniproject) 0 |
|---|
| 98 | } elseif {[string index $opt 0] eq "c"} { |
|---|
| 99 | if {[string length $opt]>1} { |
|---|
| 100 | # The tol expression is part of the option |
|---|
| 101 | # |
|---|
| 102 | set expr [string range $opt 1 end] |
|---|
| 103 | } else { |
|---|
| 104 | # Next argument is the expression to compile |
|---|
| 105 | # |
|---|
| 106 | incr i |
|---|
| 107 | set expr [lindex $cmdline $i] |
|---|
| 108 | } |
|---|
| 109 | # Put expr in the list of "things" to compile |
|---|
| 110 | # |
|---|
| 111 | lappend options(compile) [list expr $expr] |
|---|
| 112 | } elseif {[string index $opt 0] eq "v"} { |
|---|
| 113 | if {[regexp {^[A|S|U|T|E|W]*$} [string range $opt 1 end] mode]} { |
|---|
| 114 | if {$mode eq ""} { |
|---|
| 115 | set mode A |
|---|
| 116 | } |
|---|
| 117 | if {[regexp {[A|S]} $mode]} { |
|---|
| 118 | set options(out,enabled) yes |
|---|
| 119 | } |
|---|
| 120 | append options(vmode) "v$mode " |
|---|
| 121 | } else { |
|---|
| 122 | append delayed_msg "\nignoring unknown verbose mode: '$opt'" |
|---|
| 123 | } |
|---|
| 124 | } elseif {[string index $opt 0] eq "m"} { |
|---|
| 125 | if {[regexp {^[A|S|U|T|E|W]*$} [string range $opt 1 end] mode]} { |
|---|
| 126 | if {$mode eq ""} { |
|---|
| 127 | set mode A |
|---|
| 128 | } |
|---|
| 129 | if {[regexp {[A|S]} $mode]} { |
|---|
| 130 | set options(out,enabled) no |
|---|
| 131 | } |
|---|
| 132 | append options(vmode) "m$mode " |
|---|
| 133 | } else { |
|---|
| 134 | append delayed_msg "\nignoring unknown mute mode: '$opt'" |
|---|
| 135 | } |
|---|
| 136 | } elseif {$opt eq "d"} { |
|---|
| 137 | if {$options(runmode) ne "" && $options(runmode) ne "interactive"} { |
|---|
| 138 | puts "Replacing previous run mode '$options(runmode)' with 'interactive'" |
|---|
| 139 | } |
|---|
| 140 | set options(runmode) "interactive" |
|---|
| 141 | } elseif {$opt eq "tolversion"} { |
|---|
| 142 | incr i |
|---|
| 143 | set options(tolversion) [lindex $cmdline $i] |
|---|
| 144 | } elseif {$opt eq "server"} { |
|---|
| 145 | # check if next argument is the port number |
|---|
| 146 | set port [lindex $cmdline [expr {$i+1}]] |
|---|
| 147 | if {[string is integer $port]} { |
|---|
| 148 | # $i+1 is an integer, should be considered as a port number |
|---|
| 149 | incr i |
|---|
| 150 | if {$port <= 0} { |
|---|
| 151 | puts "Could not start as a server: invalid port number '${port}'" |
|---|
| 152 | exit |
|---|
| 153 | } |
|---|
| 154 | if {$options(runmode) ne "" && $options(runmode) ne "server"} { |
|---|
| 155 | puts "Replacing previous run mode '$options(runmode)' with 'server'" |
|---|
| 156 | } |
|---|
| 157 | set options(runmode) "server" |
|---|
| 158 | set options(server,port) $port |
|---|
| 159 | } else { |
|---|
| 160 | puts "Could not start as a server: invalid port number '${port}'" |
|---|
| 161 | exit |
|---|
| 162 | } |
|---|
| 163 | } elseif {$opt eq "slave"} { |
|---|
| 164 | # the next argument is the port number |
|---|
| 165 | set options(server,port) [lindex $cmdline [expr {$i+1}]] |
|---|
| 166 | incr i |
|---|
| 167 | if {$options(runmode) ne "" && $options(runmode) ne "slave"} { |
|---|
| 168 | puts "Replacing previous run mode '$options(runmode)' with 'slave'" |
|---|
| 169 | } |
|---|
| 170 | set options(runmode) "slave" |
|---|
| 171 | } elseif {$opt eq "shared"} { |
|---|
| 172 | # the next argument is the port number |
|---|
| 173 | set options(shared,port) [lindex $cmdline [expr {$i+1}]] |
|---|
| 174 | incr i |
|---|
| 175 | if {$options(runmode) ne "" && $options(runmode) ne "shared"} { |
|---|
| 176 | puts "Replacing previous run mode '$options(runmode)' with 'shared'" |
|---|
| 177 | } |
|---|
| 178 | set options(runmode) "shared" |
|---|
| 179 | } elseif {$opt eq "shport"} { |
|---|
| 180 | # the next argument is the port number |
|---|
| 181 | set options(shared,port) [lindex $cmdline [expr {$i+1}]] |
|---|
| 182 | incr i |
|---|
| 183 | } else { |
|---|
| 184 | append delayed_msg "\nignoring unknown option: '$item'" |
|---|
| 185 | } |
|---|
| 186 | } else { |
|---|
| 187 | # Consider this option as a tol file to compile. |
|---|
| 188 | # |
|---|
| 189 | if {![file exists $item] || ![file readable $item]} { |
|---|
| 190 | puts "file $item does not exist or is not readable" |
|---|
| 191 | } else { |
|---|
| 192 | lappend options(compile) [list file $item] |
|---|
| 193 | } |
|---|
| 194 | } |
|---|
| 195 | incr i |
|---|
| 196 | } |
|---|
| 197 | if {$delayed_msg ne ""} { |
|---|
| 198 | std $delayed_msg |
|---|
| 199 | } |
|---|
| 200 | } |
|---|
| 201 | |
|---|
| 202 | ############################################################################### |
|---|
| 203 | # |
|---|
| 204 | # something_to_compile -- tell us if there is something to do |
|---|
| 205 | # |
|---|
| 206 | # Depending on the command line processing some tol expression or |
|---|
| 207 | # files needs to be compiled. All this is stored in options(compile) |
|---|
| 208 | # |
|---|
| 209 | # Return: |
|---|
| 210 | # |
|---|
| 211 | # true value if there is something to compile in $options(compile) |
|---|
| 212 | # false if $options(compile) is empty |
|---|
| 213 | # |
|---|
| 214 | ############################################################################### |
|---|
| 215 | proc ::tolsh::something_to_compile { } { |
|---|
| 216 | variable options |
|---|
| 217 | |
|---|
| 218 | llength $options(compile) |
|---|
| 219 | } |
|---|
| 220 | |
|---|
| 221 | ############################################################################### |
|---|
| 222 | # |
|---|
| 223 | # show_usage -- show how to invoke tolsh |
|---|
| 224 | # |
|---|
| 225 | # This proc print into stdout a message that list the valid options accepted. |
|---|
| 226 | # |
|---|
| 227 | ############################################################################### |
|---|
| 228 | proc ::tolsh::show_usage { } { |
|---|
| 229 | puts "[get_app_name] \[options] filename ...\noptions:" |
|---|
| 230 | puts { |
|---|
| 231 | -i file --> include a file but not initLibrary |
|---|
| 232 | -np --> do not load _iniproject.tol |
|---|
| 233 | -c"..." --> compile a tol expression |
|---|
| 234 | -c "..." --> compile a tol expression |
|---|
| 235 | -v?A? --> enable all output |
|---|
| 236 | -vE --> enable error output |
|---|
| 237 | -vS --> enable standard output |
|---|
| 238 | -vU --> enable user output |
|---|
| 239 | -vT --> enable trace output |
|---|
| 240 | -m?A? --> disable all output |
|---|
| 241 | -mE --> disable error output |
|---|
| 242 | -mS --> disable standard output |
|---|
| 243 | -mU --> disable user output |
|---|
| 244 | -mT --> disable trace output |
|---|
| 245 | -d --> start in dialog mode |
|---|
| 246 | -e?n? --> use english language |
|---|
| 247 | -s?p? --> use spanish language |
|---|
| 248 | -tolversion --> specify an strict tol version to start with |
|---|
| 249 | -server [port] --> start tol as a server tolsvc.<pid>.log will be the log |
|---|
| 250 | [port] is the port number where the serve will be listening. |
|---|
| 251 | |
|---|
| 252 | Multiple verbose mode is accepted in one option, for instance, |
|---|
| 253 | |
|---|
| 254 | -vUE |
|---|
| 255 | } |
|---|
| 256 | } |
|---|
| 257 | |
|---|
| 258 | ############################################################################### |
|---|
| 259 | # |
|---|
| 260 | # getArgv0 -- return the name of the app |
|---|
| 261 | # |
|---|
| 262 | ############################################################################### |
|---|
| 263 | proc ::tolsh::get_app_name {} { |
|---|
| 264 | global argv0 |
|---|
| 265 | |
|---|
| 266 | set name [file tail $argv0] |
|---|
| 267 | return [file rootname $name] |
|---|
| 268 | } |
|---|
| 269 | |
|---|
| 270 | ############################################################################### |
|---|
| 271 | # |
|---|
| 272 | # append_message -- save a message |
|---|
| 273 | # |
|---|
| 274 | ############################################################################### |
|---|
| 275 | proc ::tolsh::std { msg } { |
|---|
| 276 | variable options |
|---|
| 277 | |
|---|
| 278 | if {$options(out,enabled)} { |
|---|
| 279 | puts $msg |
|---|
| 280 | } |
|---|
| 281 | } |
|---|
| 282 | |
|---|
| 283 | #puts "starkit = [namespace exist ::starkit]" |
|---|
| 284 | #puts "topdir = [file dir $starkit::topdir]" |
|---|
| 285 | #puts "info script = [info script]" |
|---|
| 286 | #puts "starkit::startup = [starkit::startup]" |
|---|
| 287 | #puts "[ info commands starkit::* ]" |
|---|
| 288 | #puts "argv0 = $argv0" |
|---|
| 289 | |
|---|
| 290 | proc ::tolsh::setup_pkg { pkg } { |
|---|
| 291 | #puts ":tolsh::setup_pkg $pkg [namespace exist ::starkit] " |
|---|
| 292 | if {[lsearch [package names] $pkg]==-1} { |
|---|
| 293 | if {[namespace exist ::starkit]} { |
|---|
| 294 | set bindir [file dir $starkit::topdir] |
|---|
| 295 | set libdir [file join $bindir .. lib] |
|---|
| 296 | set pkg_dirs [glob -nocomplain -dir $libdir ${pkg}*] |
|---|
| 297 | if {[llength $pkg_dirs]} { |
|---|
| 298 | lappend ::auto_path [file normalize $libdir] |
|---|
| 299 | } elseif { $::tcl_platform(platform) eq "unix" && |
|---|
| 300 | $::tcl_platform(machine) eq "x86_64" } { |
|---|
| 301 | if { [ lsearch $::auto_path "/usr/lib" ] == -1 } { |
|---|
| 302 | lappend ::auto_path "/usr/lib" |
|---|
| 303 | } |
|---|
| 304 | } else { |
|---|
| 305 | set tclsh [auto_execok tclsh] |
|---|
| 306 | if {![catch { |
|---|
| 307 | exec echo puts {$::auto_path} | $tclsh |
|---|
| 308 | } ext_auto_path]} { |
|---|
| 309 | foreach p $ext_auto_path { |
|---|
| 310 | if {[lsearch $::auto_path $p]==-1} { |
|---|
| 311 | lappend ::auto_path $p |
|---|
| 312 | } |
|---|
| 313 | } |
|---|
| 314 | } |
|---|
| 315 | } |
|---|
| 316 | tclPkgUnknown ${pkg}+1 "" |
|---|
| 317 | } else { |
|---|
| 318 | set pkg_dev_dir [file normalize [file join .. $pkg]] |
|---|
| 319 | if {[file exists $pkg_dev_dir] && [file isdir $pkg_dev_dir]} { |
|---|
| 320 | lappend ::auto_path $pkg_dev_dir |
|---|
| 321 | } |
|---|
| 322 | } |
|---|
| 323 | } |
|---|
| 324 | } |
|---|
| 325 | |
|---|
| 326 | ############################################################################### |
|---|
| 327 | # |
|---|
| 328 | # setup_autopath -- |
|---|
| 329 | # |
|---|
| 330 | # Set auto_path in order to find correctly the following packages: |
|---|
| 331 | # |
|---|
| 332 | # - toltcl |
|---|
| 333 | # - rmtps_client |
|---|
| 334 | # |
|---|
| 335 | ############################################################################### |
|---|
| 336 | proc ::tolsh::setup_autopath { } { |
|---|
| 337 | logtmp "entering ::tolsh::setup_autopath" |
|---|
| 338 | |
|---|
| 339 | setup_pkg toltcl |
|---|
| 340 | setup_pkg tolcomm |
|---|
| 341 | setup_pkg tlogger |
|---|
| 342 | setup_pkg tequila |
|---|
| 343 | setup_pkg tequilas |
|---|
| 344 | |
|---|
| 345 | logtmp "auto_path = $::auto_path" |
|---|
| 346 | logtmp "leaving ::tolsh::setup_autopath" |
|---|
| 347 | } |
|---|
| 348 | |
|---|
| 349 | proc GetHomeDir { } { |
|---|
| 350 | global env |
|---|
| 351 | # Check if we're using windows |
|---|
| 352 | if { $::tcl_platform(platform) eq "windows" } { |
|---|
| 353 | package require registry 1.0 |
|---|
| 354 | set key1 {HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders} |
|---|
| 355 | set key2 {Personal} |
|---|
| 356 | set env_home [ registry get $key1 $key2 ] |
|---|
| 357 | if {[string match %USERPROFILE%* $env_home]} { |
|---|
| 358 | set env_home [string replace $env_home 0 12 $env(USERPROFILE)] |
|---|
| 359 | } |
|---|
| 360 | } else { |
|---|
| 361 | set env_home $env(HOME) |
|---|
| 362 | } |
|---|
| 363 | return $env_home |
|---|
| 364 | } |
|---|
| 365 | |
|---|
| 366 | ############################################################################### |
|---|
| 367 | # |
|---|
| 368 | # main -- entry point for tolsh application |
|---|
| 369 | # |
|---|
| 370 | ############################################################################### |
|---|
| 371 | proc ::tolsh::run { cmdline } { |
|---|
| 372 | variable options |
|---|
| 373 | |
|---|
| 374 | #logtmp "user : [ exec whoami ]" |
|---|
| 375 | logtmp "entering run with cmdline = $cmdline" |
|---|
| 376 | # Process command line options |
|---|
| 377 | # |
|---|
| 378 | getoptions $cmdline |
|---|
| 379 | logtmp "options(compile): $options(compile)" |
|---|
| 380 | logtmp "options(runmode): $options(runmode)" |
|---|
| 381 | if {![something_to_compile] && ($options(runmode) eq "")} { |
|---|
| 382 | show_usage |
|---|
| 383 | return |
|---|
| 384 | } |
|---|
| 385 | |
|---|
| 386 | logtmp "pase getoptions" |
|---|
| 387 | |
|---|
| 388 | # Ensure Toltcl is found |
|---|
| 389 | # |
|---|
| 390 | setup_autopath |
|---|
| 391 | |
|---|
| 392 | # Load Toltcl (+tol) and initLibrary if required |
|---|
| 393 | # |
|---|
| 394 | if {$options(runmode) != "server" && $options(runmode) != "shared"} { |
|---|
| 395 | package require -exact Toltcl 2.0.2 |
|---|
| 396 | tol::initkernel $options(lang) $options(vmode) |
|---|
| 397 | |
|---|
| 398 | if {$options(initlib)} { |
|---|
| 399 | tol::initlibrary $options(iniproject) |
|---|
| 400 | } |
|---|
| 401 | |
|---|
| 402 | set appdata [string trim \ |
|---|
| 403 | [lindex [::tol::info var [list Text TolAppDataPath]] 2] \"] |
|---|
| 404 | logtmp "appdata = $appdata" |
|---|
| 405 | } |
|---|
| 406 | |
|---|
| 407 | set tolcomm_dir [file join [GetHomeDir] ".tol" "tolcomm"] |
|---|
| 408 | file mkdir $tolcomm_dir |
|---|
| 409 | |
|---|
| 410 | # load rmtps_client and tolclient if required |
|---|
| 411 | # |
|---|
| 412 | if {$options(runmode) != "server" && $options(runmode) != "shared"} { |
|---|
| 413 | |
|---|
| 414 | if {[catch {package require rmtps_client} msg]} { |
|---|
| 415 | std "could not load rmtps_client: $msg" |
|---|
| 416 | } else { |
|---|
| 417 | ::rmtps_client::init [file join $tolcomm_dir "rmtps_client.log"] |
|---|
| 418 | if {[catch rmtps_client::define_TOLAPI msg]} { |
|---|
| 419 | std "could not load tol code for rmtps_client: $msg" |
|---|
| 420 | } |
|---|
| 421 | } |
|---|
| 422 | |
|---|
| 423 | if {[catch {package require tolclient} msg]} { |
|---|
| 424 | std "could not load tolclient: $msg" |
|---|
| 425 | } else { |
|---|
| 426 | ::tolclient::init [file join $tolcomm_dir "tolclient.log"] |
|---|
| 427 | if {[catch ::tolclient::define_TOLAPI msg]} { |
|---|
| 428 | std "could not load tol code for rmtps_client: $msg" |
|---|
| 429 | } |
|---|
| 430 | } |
|---|
| 431 | |
|---|
| 432 | } |
|---|
| 433 | |
|---|
| 434 | # Compile expression and tol file provided in the command line if required |
|---|
| 435 | # |
|---|
| 436 | if {$options(runmode) != "server" && $options(runmode) != "shared" \ |
|---|
| 437 | && $options(runmode) != "slave" } { |
|---|
| 438 | |
|---|
| 439 | foreach item $options(compile) { |
|---|
| 440 | if {[lindex $item 0] eq "expr"} { |
|---|
| 441 | tol::console eval [lindex $item 1] |
|---|
| 442 | } elseif {[lindex $item 0] eq "file"} { |
|---|
| 443 | tol::include [lindex $item 1] |
|---|
| 444 | } |
|---|
| 445 | } |
|---|
| 446 | |
|---|
| 447 | } |
|---|
| 448 | |
|---|
| 449 | if {$options(runmode) eq "interactive"} { |
|---|
| 450 | # assign our event handler for stdin |
|---|
| 451 | fileevent stdin readable ::tolsh::stdin_handler |
|---|
| 452 | # send a startup message and initial prompt |
|---|
| 453 | puts stdout "TOL interactive shell activated..." |
|---|
| 454 | console_prompt |
|---|
| 455 | # enter the tcl event loop |
|---|
| 456 | vwait __forever__ |
|---|
| 457 | |
|---|
| 458 | } elseif {$options(runmode) eq "server"} { |
|---|
| 459 | puts "runmode=server" |
|---|
| 460 | run_as_server $tolcomm_dir |
|---|
| 461 | |
|---|
| 462 | } elseif {$options(runmode) eq "shared"} { |
|---|
| 463 | puts "runmode=shared" |
|---|
| 464 | run_as_shared $tolcomm_dir |
|---|
| 465 | |
|---|
| 466 | } elseif {$options(runmode) eq "slave"} { |
|---|
| 467 | puts "runmode=slave" |
|---|
| 468 | run_as_slave $tolcomm_dir |
|---|
| 469 | } |
|---|
| 470 | } |
|---|
| 471 | |
|---|
| 472 | proc ::tolsh::run_as_server {tolcomm_dir} { |
|---|
| 473 | variable options |
|---|
| 474 | package require tolserver |
|---|
| 475 | |
|---|
| 476 | set shared_port [ clone ] |
|---|
| 477 | tolserver::start -port $options(server,port) \ |
|---|
| 478 | -shport $shared_port \ |
|---|
| 479 | -logfile [file join $tolcomm_dir "tolserver.log"] \ |
|---|
| 480 | -compile $options(compile) |
|---|
| 481 | vwait __forever__ |
|---|
| 482 | } |
|---|
| 483 | |
|---|
| 484 | proc ::tolsh::find_shared_port { port } { |
|---|
| 485 | puts "::tolsh::find_shared_port $port" |
|---|
| 486 | set i 0 |
|---|
| 487 | while { $i < 100 } { |
|---|
| 488 | if { [ catch { socket localhost $port } fd ] } { |
|---|
| 489 | puts "find_shared_port OK = $port" |
|---|
| 490 | return $port |
|---|
| 491 | } |
|---|
| 492 | incr port |
|---|
| 493 | incr i |
|---|
| 494 | } |
|---|
| 495 | puts "find_shared_port FAIL!" |
|---|
| 496 | return 0 |
|---|
| 497 | } |
|---|
| 498 | |
|---|
| 499 | proc ::tolsh::clone {} { |
|---|
| 500 | variable options |
|---|
| 501 | |
|---|
| 502 | puts "::tolsh::clone" |
|---|
| 503 | set tolsh [list [info nameofexecutable] ] |
|---|
| 504 | if { $starkit::tolsh_mode ne "starpack" } { |
|---|
| 505 | lappend tolsh $::argv0 |
|---|
| 506 | } |
|---|
| 507 | set shared_port [ find_shared_port 20458 ] |
|---|
| 508 | if { !$shared_port } { |
|---|
| 509 | puts "::tolsh::clone: could not find a valid port for shared data" |
|---|
| 510 | exit |
|---|
| 511 | } |
|---|
| 512 | eval exec $tolsh -shared $shared_port & |
|---|
| 513 | after 5000 ;# wait for data sharing are created by 'shared' |
|---|
| 514 | puts "exec slave" |
|---|
| 515 | eval exec $tolsh -slave $options(server,port) -shport $shared_port & |
|---|
| 516 | return $shared_port |
|---|
| 517 | } |
|---|
| 518 | |
|---|
| 519 | proc ::tolsh::run_as_shared { tolcomm_dir } { |
|---|
| 520 | package require tolshared |
|---|
| 521 | variable options |
|---|
| 522 | |
|---|
| 523 | tolshared::start $options(shared,port) $tolcomm_dir |
|---|
| 524 | } |
|---|
| 525 | |
|---|
| 526 | proc ::tolsh::run_as_slave { tolcomm_dir } { |
|---|
| 527 | variable options |
|---|
| 528 | package require tolslave |
|---|
| 529 | |
|---|
| 530 | tolslave::start -port $options(server,port) -shport $options(shared,port) \ |
|---|
| 531 | -logfile [file join $tolcomm_dir "tolslave.log"] |
|---|
| 532 | vwait __forever__ |
|---|
| 533 | } |
|---|
| 534 | |
|---|
| 535 | proc ::tolsh::console_cmd { cmd } { |
|---|
| 536 | if {$cmd eq "END" || $cmd eq "QUIT" || $cmd eq "EXIT"} { |
|---|
| 537 | exit |
|---|
| 538 | } else { |
|---|
| 539 | puts stdout "unknown console command: '$cmd'" |
|---|
| 540 | } |
|---|
| 541 | } |
|---|
| 542 | |
|---|
| 543 | proc ::tolsh::console_eval { tol_stms } { |
|---|
| 544 | set con_objs0 [tol::console stack list] |
|---|
| 545 | tol::console eval $tol_stms |
|---|
| 546 | set con_objs1 [tol::console stack list] |
|---|
| 547 | if {[llength $con_objs1]>[llength $con_objs0]} { |
|---|
| 548 | puts stdout [lindex [lindex $con_objs1 end] 2] |
|---|
| 549 | } |
|---|
| 550 | } |
|---|
| 551 | |
|---|
| 552 | proc ::tolsh::console_prompt {} { |
|---|
| 553 | puts -nonewline stdout \ |
|---|
| 554 | "[clock format [clock seconds] -format %H:%M:%S] TOL> " |
|---|
| 555 | flush stdout |
|---|
| 556 | } |
|---|
| 557 | |
|---|
| 558 | proc ::tolsh::stdin_handler {} { |
|---|
| 559 | # get the data from stdin |
|---|
| 560 | # |
|---|
| 561 | gets stdin data |
|---|
| 562 | if {[string index $data 0] eq "\\"} { |
|---|
| 563 | console_cmd [string toupper [string range $data 1 end]] |
|---|
| 564 | } else { |
|---|
| 565 | console_eval $data |
|---|
| 566 | } |
|---|
| 567 | # return a new pseudo-prompt |
|---|
| 568 | console_prompt |
|---|
| 569 | return |
|---|
| 570 | } |
|---|
| 571 | |
|---|
| 572 | proc logtmp { msg } { |
|---|
| 573 | #return |
|---|
| 574 | set user [ exec whoami ] |
|---|
| 575 | set fd [ open "/tmp/tolsh.${user}.log" a ] |
|---|
| 576 | puts $fd $msg |
|---|
| 577 | flush $fd |
|---|
| 578 | close $fd |
|---|
| 579 | } |
|---|
| 580 | |
|---|
| 581 | ::tolsh::run $argv |
|---|