aboutsummaryrefslogtreecommitdiff
path: root/lib/os/exec/exec.go
diff options
context:
space:
mode:
authorShulhan <m.shulhan@gmail.com>2020-06-04 00:26:16 +0700
committerShulhan <m.shulhan@gmail.com>2020-06-04 00:26:16 +0700
commit427251e6f320849022e55510051797a10d4e9d83 (patch)
tree1d336732c82da228a4e25e7e64c1623d9885e09f /lib/os/exec/exec.go
parenta7e3a3852678175bf29e50c4c5a53a3ed2ab7921 (diff)
downloadpakakeh.go-427251e6f320849022e55510051797a10d4e9d83.tar.xz
os/exec: new package to simplify the standard "os/exec"
New extension to standard package is function ParseCommandArgs() that receive input as string and return itas command and list of arguments. Unlike strings.Fields() which only separated the field by space, ParseCommandArgs can detect possible single, double, or back quotes. Another extension is Run() function that accept the string command to be executed and their standard output and error.
Diffstat (limited to 'lib/os/exec/exec.go')
-rw-r--r--lib/os/exec/exec.go95
1 files changed, 95 insertions, 0 deletions
diff --git a/lib/os/exec/exec.go b/lib/os/exec/exec.go
new file mode 100644
index 00000000..bc661f3f
--- /dev/null
+++ b/lib/os/exec/exec.go
@@ -0,0 +1,95 @@
+// Copyright 2020, Shulhan <ms@kilabit.info>. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//
+// Package exec wrap the standar package "os/exec" to simplify calling Run
+// with stdout and stderr.
+//
+package exec
+
+import (
+ "io"
+ "os"
+ "os/exec"
+ "strings"
+)
+
+//
+// ParseCommandArgs parse the input string into command and arguments.
+// This function detect possible single, double, or back quote on arguments.
+//
+func ParseCommandArgs(in string) (cmd string, args []string) {
+ var (
+ quote rune
+ cmdArgs []string
+ )
+
+ sb := new(strings.Builder)
+
+ for _, r := range in {
+ if quote > 0 {
+ if r == quote {
+ arg := sb.String()
+ if len(arg) > 0 {
+ cmdArgs = append(cmdArgs, sb.String())
+ }
+
+ sb.Reset()
+ quote = 0
+ } else {
+ sb.WriteRune(r)
+ }
+ continue
+ }
+ if r == '\'' || r == '"' || r == '`' {
+ quote = r
+ continue
+ }
+ if r == ' ' || r == '\t' {
+ arg := sb.String()
+ if len(arg) > 0 {
+ cmdArgs = append(cmdArgs, sb.String())
+ }
+ sb.Reset()
+ continue
+ }
+ sb.WriteRune(r)
+ }
+
+ arg := sb.String()
+ if len(arg) > 0 {
+ cmdArgs = append(cmdArgs, sb.String())
+ }
+ sb.Reset()
+
+ if len(cmdArgs) > 0 {
+ cmd = cmdArgs[0]
+ }
+ if len(cmdArgs) > 1 {
+ args = cmdArgs[1:]
+ }
+
+ return cmd, args
+}
+
+//
+// Run the command and arguments in the string cmd.
+// If stdout or stderr is nil, it will default to os.Stdout and/or os.Stderr.
+//
+func Run(command string, stdout, stderr io.Writer) (err error) {
+ cmd, args := ParseCommandArgs(command)
+
+ execCmd := exec.Command(cmd, args...)
+
+ if stdout == nil {
+ stdout = os.Stdout
+ }
+ if stderr == nil {
+ stderr = os.Stderr
+ }
+ execCmd.Stdout = stdout
+ execCmd.Stderr = stderr
+
+ return execCmd.Run()
+}