...
1
2
3
4 package internal
5
6 import (
7 "os"
8
9 "golang.org/x/sys/unix"
10 )
11
12 func NewOutputInterceptor() OutputInterceptor {
13 return &genericOutputInterceptor{
14 interceptedContent: make(chan string),
15 pipeChannel: make(chan pipePair),
16 shutdown: make(chan interface{}),
17 implementation: &dupSyscallOutputInterceptorImpl{},
18 }
19 }
20
21 type dupSyscallOutputInterceptorImpl struct{}
22
23 func (impl *dupSyscallOutputInterceptorImpl) CreateStdoutStderrClones() (*os.File, *os.File) {
24
25
26 stdoutCloneFD, _ := unix.Dup(1)
27 stderrCloneFD, _ := unix.Dup(2)
28
29
30
31 flags, err := unix.FcntlInt(uintptr(stdoutCloneFD), unix.F_GETFD, 0)
32 if err == nil {
33 unix.FcntlInt(uintptr(stdoutCloneFD), unix.F_SETFD, flags|unix.FD_CLOEXEC)
34 }
35 flags, err = unix.FcntlInt(uintptr(stderrCloneFD), unix.F_GETFD, 0)
36 if err == nil {
37 unix.FcntlInt(uintptr(stderrCloneFD), unix.F_SETFD, flags|unix.FD_CLOEXEC)
38 }
39
40
41
42
43 stdoutClone := os.NewFile(uintptr(stdoutCloneFD), "stdout-clone")
44 stderrClone := os.NewFile(uintptr(stderrCloneFD), "stderr-clone")
45
46
47
48 return stdoutClone, stderrClone
49 }
50
51 func (impl *dupSyscallOutputInterceptorImpl) ConnectPipeToStdoutStderr(pipeWriter *os.File) {
52
53
54
55
56 unix.Dup2(int(pipeWriter.Fd()), 1)
57 unix.Dup2(int(pipeWriter.Fd()), 2)
58 }
59
60 func (impl *dupSyscallOutputInterceptorImpl) RestoreStdoutStderrFromClones(stdoutClone *os.File, stderrClone *os.File) {
61
62
63
64
65 unix.Dup2(int(stdoutClone.Fd()), 1)
66 unix.Dup2(int(stderrClone.Fd()), 2)
67 }
68
69 func (impl *dupSyscallOutputInterceptorImpl) ShutdownClones(stdoutClone *os.File, stderrClone *os.File) {
70
71 stdoutClone.Close()
72 stderrClone.Close()
73 }
74
View as plain text