aboutsummaryrefslogtreecommitdiffstats
path: root/eows/eows-out.go
diff options
context:
space:
mode:
Diffstat (limited to 'eows/eows-out.go')
-rw-r--r--eows/eows-out.go122
1 files changed, 122 insertions, 0 deletions
diff --git a/eows/eows-out.go b/eows/eows-out.go
new file mode 100644
index 0000000..3163b2f
--- /dev/null
+++ b/eows/eows-out.go
@@ -0,0 +1,122 @@
+package eows
+
+import (
+ "bufio"
+ "io"
+ "strings"
+ "time"
+)
+
+// scanChars - gain character by character (or as soon as one or more characters are available)
+func scanChars(data []byte, atEOF bool) (advance int, token []byte, err error) {
+ if atEOF && len(data) == 0 {
+ return 0, nil, nil
+ }
+ return len(data), data, nil
+}
+
+// _pumper is in charge to collect
+func (e *ExecOverWS) _pumper(sc *bufio.Scanner, fctCB func(s string)) {
+
+ // Select split function (default sc.ScanLines)
+ if e.OutSplit == SplitChar || e.OutSplit == SplitLineTime || e.OutSplit == SplitTime {
+ sc.Split(scanChars)
+ }
+
+ // Scan method according to split type
+ if e.OutSplit == SplitLineTime || e.OutSplit == SplitTime {
+ t0 := time.Now()
+ buf := ""
+ for sc.Scan() {
+ buf += sc.Text()
+ if time.Since(t0).Nanoseconds() > e.LineTimeSpan ||
+ (e.OutSplit == SplitLineTime && strings.Contains(buf, "\n")) {
+ fctCB(buf)
+ buf = ""
+ t0 = time.Now()
+ }
+ if e.procExited {
+ break
+ }
+ }
+ // Send remaining characters
+ if len(buf) > 0 {
+ fctCB(buf)
+ }
+
+ } else {
+
+ for sc.Scan() {
+ fctCB(sc.Text())
+ if e.procExited {
+ break
+ }
+ }
+ }
+
+}
+
+// pipePumpStdout is in charge to forward stdout in websocket
+func (e *ExecOverWS) pipePumpStdout(r io.Reader, done chan struct{}) {
+
+ sc := bufio.NewScanner(r)
+
+ e._pumper(sc, func(b string) {
+ if e.OutputCB != nil {
+ e.OutputCB(e, []byte(b), []byte{})
+ }
+ })
+
+ e.logDebug("STDOUT pump exit")
+
+ if sc.Err() != nil && !strings.Contains(sc.Err().Error(), "file already closed") {
+ e.logError("stdout scan: %v", sc.Err())
+ }
+
+ close(done)
+}
+
+// pipePumpStderr is in charge to forward stderr in websocket
+func (e *ExecOverWS) pipePumpStderr(r io.Reader) {
+
+ sc := bufio.NewScanner(r)
+
+ e._pumper(sc, func(b string) {
+ if e.OutputCB != nil {
+ e.OutputCB(e, []byte{}, []byte(b))
+ }
+ })
+
+ e.logDebug("STDERR pump exit")
+
+ if sc.Err() != nil && !strings.Contains(sc.Err().Error(), "file already closed") {
+ e.logError("stderr scan: %v", sc.Err())
+ }
+}
+
+// ptsPumpStdout is in charge to forward stdout in websocket
+// (only used when PtyMode is set)
+func (e *ExecOverWS) ptsPumpStdout(r io.Reader, done chan struct{}) {
+
+ buffer := make([]byte, 1024)
+ for {
+ n, err := r.Read(buffer)
+ if err != nil {
+ if err != io.EOF &&
+ !strings.Contains(err.Error(), "file already closed") {
+ e.logError("Error stdout read: %v", err)
+ }
+ break
+ }
+ if n == 0 {
+ continue
+ }
+ if e.OutputCB != nil {
+ e.OutputCB(e, buffer[:n], []byte{})
+ }
+ }
+
+ close(done)
+
+ e.logDebug("Eows stdout pump exited")
+}