github.com/tendermint/tmlibs@v0.9.0/cli/helper.go (about) 1 package cli 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 "io/ioutil" 8 "os" 9 "path/filepath" 10 ) 11 12 // WriteConfigVals writes a toml file with the given values. 13 // It returns an error if writing was impossible. 14 func WriteConfigVals(dir string, vals map[string]string) error { 15 data := "" 16 for k, v := range vals { 17 data = data + fmt.Sprintf("%s = \"%s\"\n", k, v) 18 } 19 cfile := filepath.Join(dir, "config.toml") 20 return ioutil.WriteFile(cfile, []byte(data), 0666) 21 } 22 23 // RunWithArgs executes the given command with the specified command line args 24 // and environmental variables set. It returns any error returned from cmd.Execute() 25 func RunWithArgs(cmd Executable, args []string, env map[string]string) error { 26 oargs := os.Args 27 oenv := map[string]string{} 28 // defer returns the environment back to normal 29 defer func() { 30 os.Args = oargs 31 for k, v := range oenv { 32 os.Setenv(k, v) 33 } 34 }() 35 36 // set the args and env how we want them 37 os.Args = args 38 for k, v := range env { 39 // backup old value if there, to restore at end 40 oenv[k] = os.Getenv(k) 41 err := os.Setenv(k, v) 42 if err != nil { 43 return err 44 } 45 } 46 47 // and finally run the command 48 return cmd.Execute() 49 } 50 51 // RunCaptureWithArgs executes the given command with the specified command 52 // line args and environmental variables set. It returns string fields 53 // representing output written to stdout and stderr, additionally any error 54 // from cmd.Execute() is also returned 55 func RunCaptureWithArgs(cmd Executable, args []string, env map[string]string) (stdout, stderr string, err error) { 56 oldout, olderr := os.Stdout, os.Stderr // keep backup of the real stdout 57 rOut, wOut, _ := os.Pipe() 58 rErr, wErr, _ := os.Pipe() 59 os.Stdout, os.Stderr = wOut, wErr 60 defer func() { 61 os.Stdout, os.Stderr = oldout, olderr // restoring the real stdout 62 }() 63 64 // copy the output in a separate goroutine so printing can't block indefinitely 65 copyStd := func(reader *os.File) *(chan string) { 66 stdC := make(chan string) 67 go func() { 68 var buf bytes.Buffer 69 // io.Copy will end when we call reader.Close() below 70 io.Copy(&buf, reader) 71 stdC <- buf.String() 72 }() 73 return &stdC 74 } 75 outC := copyStd(rOut) 76 errC := copyStd(rErr) 77 78 // now run the command 79 err = RunWithArgs(cmd, args, env) 80 81 // and grab the stdout to return 82 wOut.Close() 83 wErr.Close() 84 stdout = <-*outC 85 stderr = <-*errC 86 return stdout, stderr, err 87 }