The exec command treats ampersands (&) in its arguments specially, e.g. for making execution asynchronous. This can be a problem if an argument, like an URL, contains ampersamds.
[email protected] (Petteri K) writes in the comp.lang.tcl newsgroup: Would anybody know a workaround in case $url contains character '&' e.g. http://127.0.0.1/cgi-bin/script?var1=abc&var2=xyz
Benjamin Riefenstahl replied: exec plays tricks with quoting which make it impossible for me to get the right command executed in Tcl 8.3.4. What works on W2K here though is this:
set url "http://www.tcl.tk?hello&hi" set shell [open "|[file join $env(COMSPEC)]" w] fconfigure $shell -buffering line puts $shell "start \"\" \"$url\"" puts $shell exit close $shell
I hope this works on Windows 9x/Me, too.
CL suggests: In the context of avoiding exec's unescapable special characters, I prefer to use the far-too-little-understood << argument, in the manner of [slightly edited]:
set url http://ats.nist.gov/cgi-bin/cgi.tcl/echo.cgi?hello=1&hi=2 exec [file join $env(COMSPEC)] << "start \"\" \"$url\" \n exit \n"
Here is the simplest way that I've found, and I use it in my mindweb [L1 ]. It relies on the rundll utility available with some versions of Windows.
proc goUrl x { global tcl_platform if {$tcl_platform(platform) eq "windows"} { set x [regsub -all -nocase {htm} $x {ht%6D}] exec rundll32 url.dll,FileProtocolHandler $x & } } ;# This definitely works on Win95 and Win98.
See invoking browsers --Ro
For Unix/Linux, it is highly probable that the line
set shell [open "|/bin/sh" w]
works as well (just in place of the "start" command, you'd have to substitute a more specific one...) Actually:
set shell [ open "|/bin/sh -s 2>@stdout" w+ ] fconfigure $fid -blocking off fconfigure $fid -buffering line
Comes closer to doing what is expected... -sluggo
And when time comes to read it off, something like:
while { [ gets $shell line ] >= 0 } { append retval "$line\n" after 1 }
Will get you past things that buffer, like ps. The after 1' seems to be quite magical in the case of buffering, whereas after 0' does nothing useful.
But one idea for more cross-platformity: Unix has (guaranteed?) env(SHELL) to give the default shell; Windows has env(COMSPEC), Mac I don't know. Would it be worthwile to unify these into a, say, ::tcl_platform(shell) element? (RS)
No, auto_execok should cover that.