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  }