// This file is part of arduino-cli. // // Copyright 2020 ARDUINO SA (http://www.arduino.cc/) // // This software is released under the GNU General Public License version 3, // which covers the main part of arduino-cli. // The terms of this license can be found at: // https://www.gnu.org/licenses/gpl-3.0.en.html // // You can be released from the requirements of the above licenses by purchasing // a commercial license. Buying such a license is mandatory if you want to // modify or otherwise use the software for commercial activities involving the // Arduino software without disclosing the source code of your own applications. // To purchase a commercial license, send an email to license@arduino.cc. package executils import ( "bytes" "io" "os/exec" ) // PipeCommands executes the commands received as input by feeding the output of // one to the input of the other, exactly like Unix Pipe (|). // Returns the output of the final command and the eventual error. // // code inspired by https://gist.github.com/tyndyll/89fbb2c2273f83a074dc func PipeCommands(commands ...*exec.Cmd) ([]byte, error) { var errorBuffer, outputBuffer bytes.Buffer pipeStack := make([]*io.PipeWriter, len(commands)-1) i := 0 for ; i < len(commands)-1; i++ { stdinPipe, stdoutPipe := io.Pipe() commands[i].Stdout = stdoutPipe commands[i].Stderr = &errorBuffer commands[i+1].Stdin = stdinPipe pipeStack[i] = stdoutPipe } commands[i].Stdout = &outputBuffer commands[i].Stderr = &errorBuffer if err := call(commands, pipeStack); err != nil { return nil, err } return outputBuffer.Bytes(), nil } func call(stack []*exec.Cmd, pipes []*io.PipeWriter) (err error) { if stack[0].Process == nil { if err = stack[0].Start(); err != nil { return err } } if len(stack) > 1 { if err = stack[1].Start(); err != nil { return err } defer func() { pipes[0].Close() err = call(stack[1:], pipes[1:]) }() } return stack[0].Wait() } // TellCommandNotToSpawnShell avoids that the specified Cmd display a small // command prompt while runnning on Windows. It has no effects on other OS. func TellCommandNotToSpawnShell(cmd *exec.Cmd) { tellCommandNotToSpawnShell(cmd) }