-
Notifications
You must be signed in to change notification settings - Fork 8
/
proto_1_0.go
70 lines (58 loc) · 1.46 KB
/
proto_1_0.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
package main
import (
"os"
"os/exec"
)
func proto_1_0(inFlag, outFlag bool, errFlag, workdir string, args []string) error {
const stdoutMarker = 0x00
const stderrMarker = 0x01
proc := exec.Command(args[0], args[1:]...)
proc.Dir = workdir
logger.Printf("Command path: %v\n", proc.Path)
// The channel is buffered to reduce waiting time when exchanging acks
// between the main routine and io routines.
doneChan := make(chan bool, 3)
doneCount := 0
if inFlag {
wrapStdin(proc, os.Stdin, doneChan)
doneCount++
}
if outFlag {
wrapStdout(proc, os.Stdout, stdoutMarker, doneChan)
doneCount++
}
switch errFlag {
case "out":
if outFlag {
wrapStderr(proc, os.Stdout, stdoutMarker, doneChan)
doneCount++
}
case "err":
wrapStderr(proc, os.Stdout, stderrMarker, doneChan)
doneCount++
case "nil":
// no-op
default:
logger.Panicf("undefined redirect: '%v'\n", errFlag)
}
// Initial ack to make sure all pipes have been connected
for i := 0; i < doneCount; i++ {
<-doneChan
}
// FIXME: perform proper handshake instead
err := proc.Start()
fatal_if(err)
// Finishing ack to ensure all pipes were closed
for i := 0; i < doneCount; i++ {
<-doneChan
}
err = proc.Wait()
if e, ok := err.(*exec.Error); ok {
// This shouldn't really happen in practice because we check for
// program existence in Elixir, before launching goon
logger.Printf("Run ERROR: %v\n", e)
os.Exit(3)
}
logger.Printf("Run FINISHED: %#v\n", err)
return err
}