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, fctOut 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")) { fctOut(buf) buf = "" t0 = time.Now() } } // Send remaining characters if len(buf) > 0 { e.OutputCB(e, "", buf) } } else { for sc.Scan() { e.OutputCB(e, sc.Text(), "") } } } // cmdPumpStdout is in charge to forward stdout in websocket func (e *ExecOverWS) cmdPumpStdout(r io.Reader, done chan struct{}) { defer func() { }() sc := bufio.NewScanner(r) e._pumper(sc, func(bufOut string) { e.OutputCB(e, bufOut, "") }) if sc.Err() != nil && !strings.Contains(sc.Err().Error(), "file already closed") { e.logError("stdout scan: %v", sc.Err()) } close(done) } // cmdPumpStderr is in charge to forward stderr in websocket func (e *ExecOverWS) cmdPumpStderr(r io.Reader) { defer func() { }() sc := bufio.NewScanner(r) e._pumper(sc, func(bufErr string) { e.OutputCB(e, "", bufErr) }) if sc.Err() != nil && !strings.Contains(sc.Err().Error(), "file already closed") { e.logError("stderr scan: %v", sc.Err()) } }