From: pmarin on 29 Mar 2010 14:18 Hi all. I want to send a list to a program and to capture the output. currently I am using a 'chan pipe' whith 'exec'. Is it the correct way? How can I do the same using 'open "| ..."' The piece of code: proc dmenu_run {} { if {[uptodate]} { set str "exec dmenu $::argv < $::CACHE" catch {exec [{*}$str] } } else { set pipe [chan pipe] foreach f [generate_cache] { puts [lindex $pipe 1] $f } close [lindex $pipe 1] set str "exec dmenu $::argv <@[lindex $pipe 0]" catch {exec [{*}$str] } close [lindex $pipe 0] } }
From: Alexandre Ferrieux on 29 Mar 2010 15:03 On Mar 29, 8:18 pm, pmarin <pacog...(a)gmail.com> wrote: > Hi all. > > I want to send a list to a program and to capture the output. > currently I am using a 'chan pipe' whith 'exec'. Is it the correct > way? How can I do the same using 'open "| ..."' > > The piece of code: > > [...] > set pipe [chan pipe] > foreach f [generate_cache] { > puts [lindex $pipe 1] $f > } > close [lindex $pipe 1] > set str "exec dmenu $::argv <@[lindex $pipe 0]" > catch {exec [{*}$str] } > close [lindex $pipe 0] This code is problematic because it may deadlock if [generate_cache]'s output doesn't fit in the pipe's buffer (since you must have written everything before spawning the child process). Here are several ways: (1) set res [exec dmenu {*}$::argv << [join [generate_cache] \n]] (2) set f [open "|dmenu $::argv 2>@ stderr" r+] puts $f [join [generate_cache] \n] close $f w set res [read $f] close $f (3) foreach {pr pw} [chan pipe] break set f [open "|dmenu $::argv <@ $pr 2>@ stderr" r] close $pr puts $pw [join [generate_cache] \n] close $pw set res [read $f] close $f -Alex
From: pmarin on 29 Mar 2010 15:07 On Mar 29, 9:03 pm, Alexandre Ferrieux <alexandre.ferri...(a)gmail.com> wrote: > On Mar 29, 8:18 pm, pmarin <pacog...(a)gmail.com> wrote: > > > > > Hi all. > > > I want to send a list to a program and to capture the output. > > currently I am using a 'chan pipe' whith 'exec'. Is it the correct > > way? How can I do the same using 'open "| ..."' > > > The piece of code: > > > [...] > > set pipe [chan pipe] > > foreach f [generate_cache] { > > puts [lindex $pipe 1] $f > > } > > close [lindex $pipe 1] > > set str "exec dmenu $::argv <@[lindex $pipe 0]" > > catch {exec [{*}$str] } > > close [lindex $pipe 0] > > This code is problematic because it may deadlock if [generate_cache]'s > output doesn't fit in the pipe's buffer (since you must have written > everything before spawning the child process). > > Here are several ways: > > (1) > set res [exec dmenu {*}$::argv << [join [generate_cache] \n]] > > (2) > set f [open "|dmenu $::argv 2>@ stderr" r+] > puts $f [join [generate_cache] \n] > close $f w > set res [read $f] > close $f > > (3) > foreach {pr pw} [chan pipe] break > set f [open "|dmenu $::argv <@ $pr 2>@ stderr" r] > close $pr > puts $pw [join [generate_cache] \n] > close $pw > set res [read $f] > close $f > > -Alex I always forget the 'join' command. Thank you!
|
Pages: 1 Prev: Expect script to connect to sshd server Next: Text on canvas |