aboutsummaryrefslogtreecommitdiffstats
path: root/gosrc/pipes.go
diff options
context:
space:
mode:
authorsalaaad2 <arthurdurant263@gmail.com>2022-04-01 22:58:13 +0200
committersalaaad2 <arthurdurant263@gmail.com>2022-04-01 22:58:13 +0200
commit1758ce649422255bd2faf482c02be71ce0783865 (patch)
treec4faa014bd905a949f5c563fa91d148dacea4888 /gosrc/pipes.go
parenthehe (diff)
downloadsmith-1758ce649422255bd2faf482c02be71ce0783865.tar.gz
smith-1758ce649422255bd2faf482c02be71ce0783865.tar.bz2
smith-1758ce649422255bd2faf482c02be71ce0783865.tar.xz
smith-1758ce649422255bd2faf482c02be71ce0783865.tar.zst
smith-1758ce649422255bd2faf482c02be71ce0783865.zip
signing requests
Diffstat (limited to 'gosrc/pipes.go')
-rw-r--r--gosrc/pipes.go107
1 files changed, 107 insertions, 0 deletions
diff --git a/gosrc/pipes.go b/gosrc/pipes.go
new file mode 100644
index 0000000..f668821
--- /dev/null
+++ b/gosrc/pipes.go
@@ -0,0 +1,107 @@
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "os/exec"
+ "strings"
+)
+
+// Convert a shell command with a series of pipes into
+// correspondingly piped list of *exec.Cmd
+// If an arg has spaces, this will fail
+func RunString(s string) (string, error) {
+ buf := bytes.NewBuffer([]byte{})
+ sp := strings.Split(s, "|")
+ cmds := make([]*exec.Cmd, len(sp))
+ // create the commands
+ for i, c := range sp {
+ cs := strings.Split(strings.TrimSpace(c), " ")
+ cmd := cmdFromStrings(cs)
+ cmds[i] = cmd
+ }
+
+ cmds = AssemblePipes(cmds, nil, buf)
+ if err := RunCmds(cmds); err != nil {
+ return "", err
+ }
+
+ b := buf.Bytes()
+ return string(b), nil
+}
+
+func cmdFromStrings(cs []string) *exec.Cmd {
+ if len(cs) == 1 {
+ return exec.Command(cs[0])
+ } else if len(cs) == 2 {
+ return exec.Command(cs[0], cs[1])
+ }
+ return exec.Command(cs[0], cs[1:]...)
+}
+
+// Convert sequence of tokens into commands,
+// using "|" as a delimiter
+func RunStrings(tokens ...string) (string, error) {
+ if len(tokens) == 0 {
+ return "", nil
+ }
+ buf := bytes.NewBuffer([]byte{})
+ cmds := []*exec.Cmd{}
+ args := []string{}
+ // accumulate tokens until a |
+ for _, t := range tokens {
+ if t != "|" {
+ args = append(args, t)
+ } else {
+ cmds = append(cmds, cmdFromStrings(args))
+ args = []string{}
+ }
+ }
+ cmds = append(cmds, cmdFromStrings(args))
+ cmds = AssemblePipes(cmds, nil, buf)
+ if err := RunCmds(cmds); err != nil {
+ return "", fmt.Errorf("%s; %s", err.Error(), string(buf.Bytes()))
+ }
+
+ b := buf.Bytes()
+ return string(b), nil
+}
+
+// Pipe stdout of each command into stdin of next
+func AssemblePipes(cmds []*exec.Cmd, stdin io.Reader, stdout io.Writer) []*exec.Cmd {
+ cmds[0].Stdin = stdin
+ cmds[0].Stderr = stdout
+ // assemble pipes
+ for i, c := range cmds {
+ if i < len(cmds)-1 {
+ cmds[i+1].Stdin, _ = c.StdoutPipe()
+ cmds[i+1].Stderr = stdout
+ } else {
+ c.Stdout = stdout
+ c.Stderr = stdout
+ }
+ }
+ return cmds
+}
+
+// Run series of piped commands
+func RunCmds(cmds []*exec.Cmd) error {
+ // start processes in descending order
+ for i := len(cmds) - 1; i > 0; i-- {
+ if err := cmds[i].Start(); err != nil {
+ return err
+ }
+ }
+ // run the first process
+ if err := cmds[0].Run(); err != nil {
+ return err
+ }
+ // wait on processes in ascending order
+ for i := 1; i < len(cmds); i++ {
+ if err := cmds[i].Wait(); err != nil {
+ return err
+ }
+ }
+ return nil
+}