[tcljava-user] stdout / stdin
Brought to you by:
mdejong
From: Justin R. <ju...@ha...> - 2007-04-11 00:31:31
|
Before using Jacl, I was executing a Tcl binary via Runtime.exec. This provided me with an easy way of grabbing the input/output from the Process variable. My requirement is to capture the stdout of a untrusted Tcl script (and not the result). I just happen to put this into a file or pipe it to another Java class for processing. My problem is that now that I've moved to Jacl, I don't have a straight forward getOut/setOut. I went down the path of creating a custom Channel, but realized that all the relevant classes and methods are package private and I couldn't instantiate them. That was enough to stop me from investigating if that route would really work anyways, the Interp might just hardcode that kind of thing. So, caveat lector, I'm too lazy to investigate the writing a customer Channel route. I've seen other solution that redirect System.out. I'm not interesting in grabbing System.out because my code in running a larger system that uses System.out for its own purposes, and I can't have my code spill over into it. (Which bring up the point, Interp.java has lots of System.out and that is very annoying.) My solution was to write "gets" and "puts" since those are the only ways of outputting or inputting (correct me if I'm wrong). I'm describing it here to help other users and to provoke some comments. I based my solution on http://wiki.tcl.tk/8502 to redirect puts. First I have to push a variable into the Interp: String filename = outputFile.getCanonicalPath(); interp.eval("set outputfilename \"" + escape(filename) + "\"", TCL.EVAL_GLOBAL); interp.eval("set outputfile [open \"$outputfilename\" w+]", TCL.EVAL_GLOBAL); I then run this code: set altStdOut $outputfile set altStdErr $outputfile if ![llength [info command ::tcl::puts]] { rename puts ::tcl::puts proc puts args { set la [llength $args] if {$la<1 || $la>3} { error "usage: puts ?-nonewline? ?channel? string" } set nl \n if {[lindex $args 0]=="-nonewline"} { set nl "" set args [lrange $args 1 end] } if {[llength $args]==1} { set args [list stdout [join $args]] ; } foreach {channel s} $args break set cmd ::tcl::puts if {$nl==""} {lappend cmd -nonewline} if {$channel=="stdout"} { global altStdOut set channel $altStdOut } if {$channel=="stderr"} { global altStdErr set channel $altStdErr } lappend cmd $channel $s catch {eval $cmd} flush $channel } } It looks for the channel stdout or a default channel (which maps to stdout) and then I output them to the file, which is the worst part of this solution. I'd love to see a solution the just lets me set the OutputStream, from outside the package. For gets, I used the method from http://wiki.tcl.tk/10794. I'd like to see Jacl behave like its in a sandbox, to use in a JSR-233 fashion. In which it minimizes it's access to the System class (System.exit, System.out, System.err). Are there any efforts in this regard? justin |