+++ /dev/null
-// Helper type to run and log commands
-
-// Copyright (C) 2021 Simon Ruderich
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-package run
-
-import (
- "bytes"
- "fmt"
- "os/exec"
- "strings"
-
- "ruderich.org/simon/safcm/cmd/safcm-remote/log"
-)
-
-type Cmd struct {
- Runner Runner
- logger *log.Logger
-}
-
-func NewCmd(runner Runner, logger *log.Logger) *Cmd {
- return &Cmd{
- Runner: runner,
- logger: logger,
- }
-}
-
-// Run runs a command and return stdout and stderr.
-//
-// Use this only for commands running on our behalf where we need to parse the
-// output. Use CombinedOutput() for user commands because these should show
-// the complete output and have stdout and stderr in the proper order and not
-// split.
-func (c *Cmd) Run(module string, args ...string) ([]byte, []byte, error) {
- var stdout, stderr bytes.Buffer
- cmd := exec.Command(args[0], args[1:]...)
- cmd.Stdout = &stdout
- cmd.Stderr = &stderr
- quoted := QuoteForDebug(cmd)
- c.logger.Debugf("%s: running %s", module, quoted)
- err := c.Runner.Run(cmd)
- if stdout.Len() > 0 {
- c.logger.Debug2f("%s: command stdout:\n%s",
- module, stdout.Bytes())
- }
- if stderr.Len() > 0 {
- c.logger.Debug2f("%s: command stderr:\n%s",
- module, stderr.Bytes())
- }
- if err != nil {
- return nil, nil, fmt.Errorf(
- "%s failed: %v; stdout: %q, stderr: %q",
- quoted, err, stdout.String(), stderr.String())
- }
- return stdout.Bytes(), stderr.Bytes(), nil
-}
-
-// CombinedOutputCmd runs the command and returns its combined stdout and
-// stderr.
-func (c *Cmd) CombinedOutputCmd(module string, cmd *exec.Cmd) ([]byte, error) {
- quoted := QuoteForDebug(cmd)
- c.logger.Debugf("%s: running %s", module, quoted)
- out, err := c.Runner.CombinedOutput(cmd)
- if len(out) > 0 {
- c.logger.Debug2f("%s: command output:\n%s", module, out)
- }
- if err != nil {
- return nil, fmt.Errorf("%s failed: %v; output: %q",
- quoted, err, out)
- }
- return out, nil
-}
-
-func QuoteForDebug(cmd *exec.Cmd) string {
- // TODO: proper shell escaping, remove quotes when not necessary
- var quoted []string
- for _, x := range append([]string{cmd.Path}, cmd.Args[1:]...) {
- quoted = append(quoted, fmt.Sprintf("%q", x))
- }
- return strings.Join(quoted, " ")
-}