2020-07-04 23:00:11 +02:00
|
|
|
package progress
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
Inspired by the https://github.com/PumpkinSeed/cage module
|
2020-08-01 21:44:14 +02:00
|
|
|
*/
|
2020-07-04 23:00:11 +02:00
|
|
|
import (
|
2020-08-01 21:44:14 +02:00
|
|
|
"bufio"
|
2020-07-04 23:00:11 +02:00
|
|
|
"io"
|
|
|
|
|
"os"
|
2020-08-01 21:44:14 +02:00
|
|
|
"strings"
|
2020-07-04 23:00:11 +02:00
|
|
|
"sync"
|
2020-08-25 23:24:31 +02:00
|
|
|
|
|
|
|
|
"github.com/projectdiscovery/gologger"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
fourMegas = 4 * 1024
|
|
|
|
|
two = 2
|
2020-07-04 23:00:11 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type captureData struct {
|
2020-08-01 21:44:14 +02:00
|
|
|
backupStdout *os.File
|
|
|
|
|
writerStdout *os.File
|
|
|
|
|
backupStderr *os.File
|
|
|
|
|
writerStderr *os.File
|
|
|
|
|
waitFinishRead *sync.WaitGroup
|
2020-07-04 23:00:11 +02:00
|
|
|
}
|
|
|
|
|
|
2020-08-25 23:24:31 +02:00
|
|
|
func startCapture(writeLocker sync.Locker, stdout, stderr *strings.Builder) *captureData {
|
2020-07-04 23:00:11 +02:00
|
|
|
rStdout, wStdout, errStdout := os.Pipe()
|
|
|
|
|
if errStdout != nil {
|
|
|
|
|
panic(errStdout)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rStderr, wStderr, errStderr := os.Pipe()
|
|
|
|
|
if errStderr != nil {
|
|
|
|
|
panic(errStderr)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
c := &captureData{
|
|
|
|
|
backupStdout: os.Stdout,
|
|
|
|
|
writerStdout: wStdout,
|
|
|
|
|
|
|
|
|
|
backupStderr: os.Stderr,
|
|
|
|
|
writerStderr: wStderr,
|
|
|
|
|
|
2020-08-01 21:44:14 +02:00
|
|
|
waitFinishRead: &sync.WaitGroup{},
|
2020-07-04 23:00:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
os.Stdout = c.writerStdout
|
|
|
|
|
os.Stderr = c.writerStderr
|
|
|
|
|
|
2020-08-01 21:44:14 +02:00
|
|
|
stdCopy := func(builder *strings.Builder, reader *os.File, waitGroup *sync.WaitGroup) {
|
|
|
|
|
r := bufio.NewReader(reader)
|
2020-08-25 23:24:31 +02:00
|
|
|
buf := make([]byte, 0, fourMegas)
|
|
|
|
|
|
2020-08-01 21:44:14 +02:00
|
|
|
for {
|
|
|
|
|
n, err := r.Read(buf[:cap(buf)])
|
|
|
|
|
buf = buf[:n]
|
2020-08-25 23:24:31 +02:00
|
|
|
|
2020-08-01 21:44:14 +02:00
|
|
|
if n == 0 {
|
|
|
|
|
if err == nil {
|
|
|
|
|
continue
|
|
|
|
|
}
|
2020-08-25 23:24:31 +02:00
|
|
|
|
2020-08-01 21:44:14 +02:00
|
|
|
if err == io.EOF {
|
|
|
|
|
waitGroup.Done()
|
|
|
|
|
break
|
|
|
|
|
}
|
2020-08-25 23:24:31 +02:00
|
|
|
|
2020-08-01 21:44:14 +02:00
|
|
|
waitGroup.Done()
|
|
|
|
|
gologger.Fatalf("stdcapture error: %s", err)
|
|
|
|
|
}
|
2020-08-25 23:24:31 +02:00
|
|
|
|
2020-08-01 21:44:14 +02:00
|
|
|
if err != nil && err != io.EOF {
|
|
|
|
|
waitGroup.Done()
|
|
|
|
|
gologger.Fatalf("stdcapture error: %s", err)
|
|
|
|
|
}
|
2020-08-25 23:24:31 +02:00
|
|
|
|
|
|
|
|
writeLocker.Lock()
|
2020-08-01 21:44:14 +02:00
|
|
|
builder.Write(buf)
|
2020-08-25 23:24:31 +02:00
|
|
|
writeLocker.Unlock()
|
2020-07-04 23:00:11 +02:00
|
|
|
}
|
2020-07-08 23:13:05 +02:00
|
|
|
}
|
2020-07-04 23:00:11 +02:00
|
|
|
|
2020-08-25 23:24:31 +02:00
|
|
|
c.waitFinishRead.Add(two)
|
|
|
|
|
|
2020-08-01 21:44:14 +02:00
|
|
|
go stdCopy(stdout, rStdout, c.waitFinishRead)
|
|
|
|
|
go stdCopy(stderr, rStderr, c.waitFinishRead)
|
2020-07-04 23:00:11 +02:00
|
|
|
|
|
|
|
|
return c
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-01 21:44:14 +02:00
|
|
|
func stopCapture(c *captureData) {
|
2020-07-04 23:00:11 +02:00
|
|
|
_ = c.writerStdout.Close()
|
|
|
|
|
_ = c.writerStderr.Close()
|
|
|
|
|
|
2020-08-01 21:44:14 +02:00
|
|
|
c.waitFinishRead.Wait()
|
2020-07-08 23:13:05 +02:00
|
|
|
|
|
|
|
|
os.Stdout = c.backupStdout
|
|
|
|
|
os.Stderr = c.backupStderr
|
2020-07-04 23:00:11 +02:00
|
|
|
}
|