|
|
@ -530,6 +530,50 @@ namespace eval shellfilter::chan { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
oo::class create ansiwrap { |
|
|
|
|
|
|
|
variable o_trecord |
|
|
|
|
|
|
|
variable o_enc |
|
|
|
|
|
|
|
variable o_colour |
|
|
|
|
|
|
|
variable o_do_colour |
|
|
|
|
|
|
|
variable o_do_normal |
|
|
|
|
|
|
|
variable o_is_junction |
|
|
|
|
|
|
|
constructor {tf} { |
|
|
|
|
|
|
|
set o_trecord $tf |
|
|
|
|
|
|
|
set o_enc [dict get $tf -encoding] |
|
|
|
|
|
|
|
set settingsdict [dict get $tf -settings] |
|
|
|
|
|
|
|
if {[dict exists $settingsdict -colour]} { |
|
|
|
|
|
|
|
set o_colour [dict get $settingsdict -colour] |
|
|
|
|
|
|
|
set o_do_colour [shellfilter::ansi::+ {*}$o_colour] |
|
|
|
|
|
|
|
set o_do_normal [shellfilter::ansi::+] |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
set o_colour {} |
|
|
|
|
|
|
|
set o_do_colour "" |
|
|
|
|
|
|
|
set o_do_normal "" |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if {[dict exists $settingsdict -junction]} { |
|
|
|
|
|
|
|
set o_is_junction [dict get $settingsdict -junction] |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
set o_is_junction 0 |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
method initialize {transform_handle mode} { |
|
|
|
|
|
|
|
return [list initialize write finalize] |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
method finalize {transform_handle} { |
|
|
|
|
|
|
|
my destroy |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
method watch {transform_handle events} { |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
method write {transform_handle bytes} { |
|
|
|
|
|
|
|
set instring [encoding convertfrom $o_enc $bytes] |
|
|
|
|
|
|
|
set outstring "$o_do_colour$instring$o_do_normal" |
|
|
|
|
|
|
|
#set outstring ">>>$instring" |
|
|
|
|
|
|
|
return [encoding convertto $o_enc $outstring] |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
method meta_is_redirection {} { |
|
|
|
|
|
|
|
return $o_is_junction |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
#todo - something |
|
|
|
#todo - something |
|
|
|
oo::class create rebuffer { |
|
|
|
oo::class create rebuffer { |
|
|
|
variable o_trecord |
|
|
|
variable o_trecord |
|
|
@ -738,6 +782,64 @@ namespace eval shellfilter::chan { |
|
|
|
namespace eval shellfilter::stack { |
|
|
|
namespace eval shellfilter::stack { |
|
|
|
variable pipelines [list] |
|
|
|
variable pipelines [list] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proc status {{pipename *} args} { |
|
|
|
|
|
|
|
variable pipelines |
|
|
|
|
|
|
|
package require overtype |
|
|
|
|
|
|
|
#todo -verbose |
|
|
|
|
|
|
|
set table "" |
|
|
|
|
|
|
|
set ac1 [string repeat " " 15] |
|
|
|
|
|
|
|
set ac2 [string repeat " " 32] |
|
|
|
|
|
|
|
set ac3 [string repeat " " 80] |
|
|
|
|
|
|
|
append table "[overtype::left $ac1 channel-ident] " |
|
|
|
|
|
|
|
append table "[overtype::left $ac2 device-info] " |
|
|
|
|
|
|
|
append table "[overtype::left $ac3 stack-info]" |
|
|
|
|
|
|
|
append table \n |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
set bc1 [string repeat " " 5] ;#stack id |
|
|
|
|
|
|
|
set bc2 [string repeat " " 25] ;#transform |
|
|
|
|
|
|
|
set bc3 [string repeat " " 50] ;#settings |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
foreach k [dict keys $pipelines $pipename] { |
|
|
|
|
|
|
|
set lc [dict get $pipelines $k device localchan] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
set col1 [overtype::left $ac1 $k] |
|
|
|
|
|
|
|
set col2 [overtype::left $ac2 "localchan: $lc"] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
set stack [dict get $pipelines $k stack] |
|
|
|
|
|
|
|
if {![llength $stack]} { |
|
|
|
|
|
|
|
set col3 $ac3 |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
set rec [lindex $stack 0] |
|
|
|
|
|
|
|
set bcol1 [overtype::left $bc1 [dict get $rec -id]] |
|
|
|
|
|
|
|
set bcol2 [overtype::left $bc2 [namespace tail [dict get $rec -transform]]] |
|
|
|
|
|
|
|
set bcol3 [overtype::left $bc3 [dict get $rec -settings]] |
|
|
|
|
|
|
|
set stackrow "$bcol1 $bcol2 $bcol3" |
|
|
|
|
|
|
|
set col3 [overtype::left $ac3 $stackrow] |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
append table "$col1 $col2 $col3\n" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
foreach rec [lrange $stack 1 end] { |
|
|
|
|
|
|
|
set col1 $ac1 |
|
|
|
|
|
|
|
set col2 $ac2 |
|
|
|
|
|
|
|
if {[llength $rec]} { |
|
|
|
|
|
|
|
set bc1 [overtype::left $bc1 [dict get $rec -id]] |
|
|
|
|
|
|
|
set bc2 [overtype::left $bc2 [namespace tail [dict get $rec -transform]]] |
|
|
|
|
|
|
|
set bc3 [overtype::left $bc3 [dict get $rec -settings]] |
|
|
|
|
|
|
|
set stackrow "$bc1 $bc2 $bc3" |
|
|
|
|
|
|
|
set col3 [overtype::left $ac3 $stackrow] |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
set col3 $ac3 |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
append table "$col1 $col2 $col3\n" |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return $table |
|
|
|
|
|
|
|
} |
|
|
|
#used for output channels - we usually want to sink redirections below the floaters and down to topmost existing redir |
|
|
|
#used for output channels - we usually want to sink redirections below the floaters and down to topmost existing redir |
|
|
|
proc _get_stack_floaters {stack} { |
|
|
|
proc _get_stack_floaters {stack} { |
|
|
|
set floaters [list] |
|
|
|
set floaters [list] |
|
|
@ -1572,7 +1674,7 @@ namespace eval shellfilter { |
|
|
|
set newinner [string map [list {"} "\\\""] $a] |
|
|
|
set newinner [string map [list {"} "\\\""] $a] |
|
|
|
return "\"$newinner\"" |
|
|
|
return "\"$newinner\"" |
|
|
|
} |
|
|
|
} |
|
|
|
proc get_scriptrun_from_cmdlist_dquote_if_not {cmdlist} { |
|
|
|
proc get_scriptrun_from_cmdlist_dquote_if_not {cmdlist {shellcmdflag ""}} { |
|
|
|
set scr [auto_execok "script"] |
|
|
|
set scr [auto_execok "script"] |
|
|
|
if {[string length $scr]} { |
|
|
|
if {[string length $scr]} { |
|
|
|
#set scriptrun "( $c1 [lrange $cmdlist 1 end] )" |
|
|
|
#set scriptrun "( $c1 [lrange $cmdlist 1 end] )" |
|
|
@ -1584,8 +1686,12 @@ namespace eval shellfilter { |
|
|
|
set c1 $arg1 |
|
|
|
set c1 $arg1 |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if {[string length $shellcmdflag]} { |
|
|
|
set scriptrun "( $c1 " |
|
|
|
set scriptrun "$shellcmdflag \$($c1 " |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
set scriptrun "\$($c1 " |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
#set scriptrun "$c1 " |
|
|
|
foreach a [lrange $cmdlist 1 end] { |
|
|
|
foreach a [lrange $cmdlist 1 end] { |
|
|
|
#set a [string map [list "/" "//"] $a] |
|
|
|
#set a [string map [list "/" "//"] $a] |
|
|
|
#set a [string map [list "\"" "\\\""] $a] |
|
|
|
#set a [string map [list "\"" "\\\""] $a] |
|
|
@ -1596,8 +1702,10 @@ namespace eval shellfilter { |
|
|
|
} |
|
|
|
} |
|
|
|
append scriptrun " " |
|
|
|
append scriptrun " " |
|
|
|
} |
|
|
|
} |
|
|
|
append scriptrun " )" |
|
|
|
set scriptrun [string trim $scriptrun] |
|
|
|
return [list $scr -q -e -c $scriptrun /dev/null] |
|
|
|
append scriptrun ")" |
|
|
|
|
|
|
|
#return [list $scr -q -e -c $scriptrun /dev/null] |
|
|
|
|
|
|
|
return [list $scr -e -c $scriptrun /dev/null] |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
return $cmdlist |
|
|
|
return $cmdlist |
|
|
|
} |
|
|
|
} |
|
|
@ -1678,15 +1786,28 @@ namespace eval shellfilter { |
|
|
|
#An error can be raised if the command couldn't even launch, as opposed to a non-zero exitcode and stderr output from the command itself. |
|
|
|
#An error can be raised if the command couldn't even launch, as opposed to a non-zero exitcode and stderr output from the command itself. |
|
|
|
# |
|
|
|
# |
|
|
|
if {!$is_script} { |
|
|
|
if {!$is_script} { |
|
|
|
|
|
|
|
set experiment 0 |
|
|
|
|
|
|
|
if $experiment { |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
set results [exec {*}$commandlist] |
|
|
|
|
|
|
|
set exitinfo [list exitcode 0] |
|
|
|
|
|
|
|
} trap CHILDSTATUS {results options} { |
|
|
|
|
|
|
|
set exitcode [lindex [dict get $options -errorcode] 2] |
|
|
|
|
|
|
|
set exitinfo [list exitcode $exitcode] |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
if {[catch { |
|
|
|
if {[catch { |
|
|
|
#run process with stdout/stderr/stdin or with configured channels |
|
|
|
#run process with stdout/stderr/stdin or with configured channels |
|
|
|
#set exitinfo [shellcommand_stdout_stderr $commandlist $outchan $errchan $inpipechan {*}$opts] |
|
|
|
#set exitinfo [shellcommand_stdout_stderr $commandlist $outchan $errchan $inpipechan {*}$opts] |
|
|
|
set exitinfo [shellcommand_stdout_stderr $commandlist $outchan $errchan stdin {*}$opts] |
|
|
|
set exitinfo [shellcommand_stdout_stderr $commandlist $outchan $errchan stdin {*}$opts] |
|
|
|
|
|
|
|
#puts stderr "---->exitinfo $exitinfo" |
|
|
|
|
|
|
|
|
|
|
|
#subprocess result should usually have an "exitcode" key |
|
|
|
#subprocess result should usually have an "exitcode" key |
|
|
|
#but for background execution we will get a "pids" key of process ids. |
|
|
|
#but for background execution we will get a "pids" key of process ids. |
|
|
|
} errMsg]} { |
|
|
|
} errMsg]} { |
|
|
|
set exitinfo [list error "$errMsg" source shellcommand_stdout_stderr] |
|
|
|
set exitinfo [list error "$errMsg" source shellcommand_stdout_stderr] |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
if {[catch { |
|
|
|
if {[catch { |
|
|
|
#script result |
|
|
|
#script result |
|
|
@ -2014,6 +2135,7 @@ namespace eval shellfilter { |
|
|
|
chan configure $outchan -translation $outtranslation |
|
|
|
chan configure $outchan -translation $outtranslation |
|
|
|
chan configure $errchan -translation $outtranslation |
|
|
|
chan configure $errchan -translation $outtranslation |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#puts stderr "chan configure $wrerr [chan configure $wrerr]" |
|
|
|
if {$debug} { |
|
|
|
if {$debug} { |
|
|
|
::shellfilter::log::write $debugname "COMMAND [list $commandlist] strlen:[string length $commandlist] llen:[llength $commandlist]" |
|
|
|
::shellfilter::log::write $debugname "COMMAND [list $commandlist] strlen:[string length $commandlist] llen:[llength $commandlist]" |
|
|
|
} |
|
|
|
} |
|
|
@ -2025,6 +2147,14 @@ namespace eval shellfilter { |
|
|
|
::shellfilter::log::write $runtag "LAUNCH open |[concat $commandlist [list 2>@$wrerr <@$inchan]] [list RDONLY]" |
|
|
|
::shellfilter::log::write $runtag "LAUNCH open |[concat $commandlist [list 2>@$wrerr <@$inchan]] [list RDONLY]" |
|
|
|
#set rdout [open |[concat $commandlist [list 2>@$wrerr]] a+] |
|
|
|
#set rdout [open |[concat $commandlist [list 2>@$wrerr]] a+] |
|
|
|
#set rdout [open |[concat $commandlist [list 2>@$wrerr]] [list RDWR]] |
|
|
|
#set rdout [open |[concat $commandlist [list 2>@$wrerr]] [list RDWR]] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# If we don't redirect stderr to our own tcl-based channel - then the transforms don't get applied. |
|
|
|
|
|
|
|
# This is the whole reason we need these file-event loops. |
|
|
|
|
|
|
|
# Ideally we need something like exec,open in tcl that interacts with transformed channels directly and emits as it runs, not only at termination |
|
|
|
|
|
|
|
# - and that at least appears like a terminal to the called command. |
|
|
|
|
|
|
|
#set rdout [open |[concat $commandlist [list 2>@stderr <@$inchan]] [list RDONLY]] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
set rdout [open |[concat $commandlist [list 2>@$wrerr <@$inchan]] [list RDONLY]] |
|
|
|
set rdout [open |[concat $commandlist [list 2>@$wrerr <@$inchan]] [list RDONLY]] |
|
|
|
} |
|
|
|
} |
|
|
|
set command_pids [pid $rdout] |
|
|
|
set command_pids [pid $rdout] |
|
|
|