Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

stdout redirection

Tags:

tcl

I am working with a procedure in tcl over which I have no control. It puts out a lot of verbose on the output window like:

Response:<?xml version='1.0' encoding='UTF-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body><soapenv:Fault><faultcode>soapenv:Server</faultcode><faultstring>Item not valid: The specified Standard SIP1 Profile was not found</faultstring><detail><axlError><axlcode>5007</axlcode><axlmessage>Item not valid: The specified Standard SIP1 Profile was not found</axlmessage><request>updatePhone</request></axlError></detail></soapenv:Fault></soapenv:Body></soapenv:Envelope>

Is there any way i can redirect this stdout to a variable? I am new to tcl and am not aware how i can do this.

like image 619
user2012195 Avatar asked Jul 18 '26 15:07

user2012195


2 Answers

If you are using Tcl 8.6, you can trap all the output to stdout by adding a suitable transform via chan push:

# Use a class to simplify the capture code
oo::class create CapturingTransform {
    variable var
    constructor {varName} {
        # Make an alias from the instance variable to the global variable
        my eval [list upvar \#0 $varName var]
    }
    method initialize {handle mode} {
        if {$mode ne "write"} {error "can't handle reading"}
        return {finalize initialize write}
    }
    method finalize {handle} {
        # Do nothing, but mandatory that it exists
    }

    method write {handle bytes} {
        append var $bytes
        # Return the empty string, as we are swallowing the bytes
        return ""
    }
}

# Attach an instance of the capturing transform
set myBuffer ""
chan push stdout [CapturingTransform new myBuffer]

# ... call the problem code as normal ...

# Detach to return things to normal
chan pop stdout

Things to note: this captures all output on the channel, however produced (it even works across threads or where the output is generated at the C level), and this puts bytes into myBuffer as the capturing is applied after the conversion to the channel's configured encoding. And it requires 8.6; the API concerned wasn't exposed to scripts in earlier versions (though it's C-equivalent was used by some extensions for things such as SSL support).

like image 174
Donal Fellows Avatar answered Jul 21 '26 06:07

Donal Fellows


Always the same question..

You have a few options:

  • Write a Tcl Extension in C that exposes Tcl_SetStdChannel to script level. Probably one of the better solutions, but not that easy.

  • Rename and replace puts. For most output that comes from libs that write to stdout without being asked for this should be good enough. But there are a lot of other ways how someone could write something to stdout, e.g. chan puts, fcopy, exec echo foo >@stdout. I think that it is hard to rewrite all possible places where a channel can be used.

  • Remove stdout from the interp. Downside is that you don't get the output. You can get stdout back after the procedure has run. For example:

    set tint [interp create]
    interp transfer {} stdout $tint
    ... call your stuff here...
    interp share $tint stdout {}
    interp delete $int
    

    Note that you should probably not create the interp each time you need that. Create one once, and reuse it.

like image 25
Johannes Kuhn Avatar answered Jul 21 '26 07:07

Johannes Kuhn



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!