rendered paste body; ----------------------------------------------
; stdcatch.mrc - by Collective
; ----------------------------------------------
;
; This script provides an interface to run
; applications and read from stdout/stderr. It
; also provides a method to write to stdin.
;
; All reading is done one line at a time. Long
; lines are (currently) not split up and will
; cause errors.
;
; Usage:
; $stdcatch(<command-line>)
; $stdcatch.close(<id>)
; $stdcatch.write(<id>,<string>)
;
; $stdcatch() returns an ID (actually $ticks)
; for use with .close, .write and on SIGNAL
;
; On failure all commands return 0 and /may/
; send an ERR signal with the error message.
;
; Results are sent as /signal stdcatch,
; possible values for $1- are:
;
; START <id> - Process started
; STDOUT <id> [string] - Line from stdout
; STDERR <id> [string] - Line from stderr
; END <id> - End of streams reached/
; Process terminated
; ERR <id> [string] - An error occurred
; For debugging
on *:SIGNAL:stdcatch:{
echo -a $1-
}
; Main aliases
alias stdcatch {
var %i = $ticks
stdcatch.close %i
.comopen stdcatch.shell $+ %i WScript.Shell
if ( $comerr ) {
stdcatch.throwerror %i Couldn't open WScript.Shell (stdcatch $1-) | return 0
}
if ( !$com(stdcatch.shell $+ %i,Exec,1,bstr,$1-,dispatch* stdcatch.exec $+ %i) ) || ( !$com(stdcatch.exec $+ %i) ) {
stdcatch.throwerror %i Exec() failed (stdcatch $1-) | return 0
}
.signal stdcatch START %i
if ( !$com(stdcatch.exec $+ %i,StdOut,2,dispatch* stdcatch.out $+ %i) ) || ( !$com(stdcatch.out $+ %i) ) {
stdcatch.throwerror %i Couldn't open StdOut (stdcatch $1-) | return 0
}
if ( !$com(stdcatch.exec $+ %i,StdErr,2,dispatch* stdcatch.err $+ %i) ) || ( !$com(stdcatch.err $+ %i) ) {
stdcatch.throwerror %i Couldn't open StdErr (stdcatch $1-) | return 0
}
if ( !$com(stdcatch.exec $+ %i,StdIn,2,dispatch* stdcatch.in $+ %i) ) || ( !$com(stdcatch.in $+ %i) ) {
stdcatch.throwerror %i Couldn't open StdIn (stdcatch $1-) | return 0
}
noop $comcall(stdcatch.out $+ %i,stdcatch.ready %i Out,AtEndOfStream,2)
noop $comcall(stdcatch.err $+ %i,stdcatch.ready %i Err,AtEndOfStream,2)
return %i
:error | stdcatch.throwerror $1 $error | reseterror | return 0
}
alias stdcatch.close {
if ( $com(stdcatch.shell $+ $1) ) { .comclose $v1 }
if ( $com(stdcatch.exec $+ $1) ) {
noop $com($v1,Terminate,1)
.comclose $v1
.signal stdcatch END $1
}
if ( $com(stdcatch.out $+ $1) ) { .comclose $v1 }
if ( $com(stdcatch.err $+ $1) ) { .comclose $v1 }
if ( $com(stdcatch.in $+ $1) ) { .comclose $v1 }
return 1
:error | .stdcatch.throwerror $1 $error (stdcatch.close $1-) | reseterror | return 0
}
alias stdcatch.write {
if ( !$com(stdcatch.in $+ $1) ) {
stdcatch.throwerror $1 No such process (stdcatch.write $1-) | return 0
}
return $com(stdcatch.in $+ $1,Write,3,bstr,$2-)
:error | stdcatch.throwerror $1 $error (stdcatch.write $1-) | reseterror | return 0
}
alias -l stdcatch.throwerror {
.signal stdcatch ERR $1-
$iif($show,stdcatch.close $1)
}
; Used internally, can't be local due to use of $comcall
alias stdcatch.readline {
if ( $comerr ) { stdcatch.throwerror $1 $!comerr returned $v1 (stdcatch.readline $1-) | return }
.signal stdcatch STD $+ $upper($2) $1 $com($+(stdcatch.,$2,$1)).result
return $comcall($+(stdcatch.,$2,$1),stdcatch.ready $1-,AtEndOfStream,2)
:error | stdcatch.throwerror $1 $error | reseterror | return
}
alias stdcatch.ready {
if ( $comerr ) { stdcatch.throwerror $1 $!comerr returned $v1 (stdcatch.ready $1-) | return }
if ( $com($+(stdcatch.,$2,$1)).result ) {
.comclose $+(stdcatch.,$2,$1)
if ( !$com(stdcatch.out $+ $1) ) && ( !$com(stdcatch.err $+ $1) ) {
stdcatch.close $1
}
}
else { noop $comcall($+(stdcatch.,$2,$1),stdcatch.readline $1-,ReadLine,1) }
return 1
:error | stdcatch.throwerror $1 $error | reseterror | return
}