This repository has been archived by the owner on May 31, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 9
/
cmdfunc.go
88 lines (73 loc) · 1.55 KB
/
cmdfunc.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package procs
import (
"bytes"
"os/exec"
"github.com/Roman2K/scat"
)
var (
_ Proc = CmdFunc(nil)
_ Proc = CmdInFunc(nil)
_ Proc = CmdOutFunc(nil)
)
type CmdFunc func(*scat.Chunk) (*exec.Cmd, error)
func (fn CmdFunc) Process(c *scat.Chunk) <-chan Res {
outFn := CmdOutFunc(func(*scat.Chunk) (cmd *exec.Cmd, err error) {
cmd, err = fn(c)
if err != nil {
return
}
cmd.Stdin = c.Data().Reader()
return
})
return outFn.Process(c)
}
func (CmdFunc) Finish() error {
return nil
}
type CmdInFunc CmdFunc
func (fn CmdInFunc) Process(c *scat.Chunk) <-chan Res {
return InplaceFunc(fn.process).Process(c)
}
func (fn CmdInFunc) process(c *scat.Chunk) (err error) {
cmd, err := fn(c)
if err != nil {
return
}
cmd.Stdin = c.Data().Reader()
return runCaptureStderr(cmd)
}
func (CmdInFunc) Finish() error {
return nil
}
type CmdOutFunc CmdFunc
func (fn CmdOutFunc) Process(c *scat.Chunk) <-chan Res {
return ChunkFunc(fn.process).Process(c)
}
func (fn CmdOutFunc) process(c *scat.Chunk) (new *scat.Chunk, err error) {
cmd, err := fn(c)
if err != nil {
return
}
buf := &bytes.Buffer{}
cmd.Stdout = buf
err = runCaptureStderr(cmd)
new = c.WithData(scat.BytesData(buf.Bytes()))
return
}
func (CmdOutFunc) Finish() error {
return nil
}
func runCaptureStderr(cmd *exec.Cmd) (err error) {
var errBuf *bytes.Buffer
if cmd.Stderr == nil {
errBuf = &bytes.Buffer{}
cmd.Stderr = errBuf
}
err = cmd.Run()
if exit, ok := err.(*exec.ExitError); ok {
if len(exit.Stderr) == 0 && errBuf != nil {
exit.Stderr = errBuf.Bytes()
}
}
return
}