From 5bb2d6d1b4d010f3934f715cc2914f17125affad Mon Sep 17 00:00:00 2001 From: Shane C Date: Thu, 4 Jul 2024 16:40:13 -0400 Subject: [PATCH 1/7] new runner structure --- linux/interface.go | 25 ++++++++++++++++ linux/run.go | 73 ++++++++++++++++++++++++++++++++++++++++++++++ linux/utils.go | 37 +++++++++++++++++++++++ 3 files changed, 135 insertions(+) create mode 100644 linux/interface.go create mode 100644 linux/run.go create mode 100644 linux/utils.go diff --git a/linux/interface.go b/linux/interface.go new file mode 100644 index 0000000..9cac60b --- /dev/null +++ b/linux/interface.go @@ -0,0 +1,25 @@ +package linux + +import ( + "errors" +) + +type LinuxCommand struct { + Options CommandOptions +} + +type CommandOptions struct { + Env map[string]string + Sources map[string]string + Command string + Args []string + Cwd string + Shell string +} + +// Errors +var ( + ErrFetchingCwd = errors.New("error fetching cwd") + ErrRunningCmd = errors.New("error running command") + ErrCommandNotFound = errors.New("error command not found") +) diff --git a/linux/run.go b/linux/run.go new file mode 100644 index 0000000..321599b --- /dev/null +++ b/linux/run.go @@ -0,0 +1,73 @@ +package linux + +import ( + "errors" + "fmt" + "os" + "os/exec" +) + +func NewCommand(options CommandOptions) (*LinuxCommand, error) { + + if len(options.Shell) == 0 { + options.Shell = "/bin/bash" + } + + if len(options.Cwd) == 0 { + cwd, err := os.Getwd() + if err != nil { + return nil, ErrFetchingCwd + } + options.Cwd = cwd + } + + return &LinuxCommand{ + Options: options, + }, nil + +} + +func (cmd *LinuxCommand) Run() error { + + command := exec.Command(cmd.Options.Shell, "-c", cmd.Options.Command) + command.Args = append(command.Args, cmd.Options.Args...) + + // Loop through env to format and add them to the command. + for key, value := range cmd.Options.Env { + command.Env = append(command.Env, fmt.Sprintf("%s=%s", key, value)) + } + + commandExists, err := cmd.doesCommandExist(cmd.Options.Command) + if err != nil { + return err + } + + if !commandExists { + return ErrCommandNotFound + } + + if err := command.Start(); err != nil { + var exitErr *exec.ExitError + if errors.As(err, &exitErr) { + if exitErr.ExitCode() == 127 { + return ErrCommandNotFound + } else { + return fmt.Errorf("%w: %w", ErrRunningCmd, err) + } + } + } + + if err := command.Start(); err != nil { + var exitErr *exec.ExitError + if errors.As(err, &exitErr) { + if exitErr.ExitCode() == 127 { + return ErrCommandNotFound + } else { + return fmt.Errorf("%w: %w", ErrRunningCmd, err) + } + } + } + + return nil + +} diff --git a/linux/utils.go b/linux/utils.go new file mode 100644 index 0000000..dcc5e87 --- /dev/null +++ b/linux/utils.go @@ -0,0 +1,37 @@ +package linux + +import ( + "errors" + "fmt" + "os/exec" +) + +func (cmd *LinuxCommand) doesCommandExist(command string) (bool, error) { + + shellCmd := exec.Command(cmd.Options.Shell, "-c", fmt.Sprintf("command -v %s", command)) + + if err := shellCmd.Start(); err != nil { + var exitErr *exec.ExitError + if errors.As(err, &exitErr) { + if exitErr.ExitCode() == 1 { + return false, nil + } else { + return false, ErrRunningCmd + } + } + } + + if err := shellCmd.Wait(); err != nil { + var exitErr *exec.ExitError + if errors.As(err, &exitErr) { + if exitErr.ExitCode() == 1 { + return false, nil + } else { + return false, ErrRunningCmd + } + } + } + + return true, nil + +} From f9f879e7ee6d52a07add24bb38ec299ce789d10d Mon Sep 17 00:00:00 2001 From: Shane C Date: Thu, 4 Jul 2024 16:44:26 -0400 Subject: [PATCH 2/7] remove command check in runner --- linux/run.go | 9 --------- 1 file changed, 9 deletions(-) diff --git a/linux/run.go b/linux/run.go index 321599b..f214f2e 100644 --- a/linux/run.go +++ b/linux/run.go @@ -37,15 +37,6 @@ func (cmd *LinuxCommand) Run() error { command.Env = append(command.Env, fmt.Sprintf("%s=%s", key, value)) } - commandExists, err := cmd.doesCommandExist(cmd.Options.Command) - if err != nil { - return err - } - - if !commandExists { - return ErrCommandNotFound - } - if err := command.Start(); err != nil { var exitErr *exec.ExitError if errors.As(err, &exitErr) { From 3a9d03a46f7ec9309e00624e2695bd63a788c718 Mon Sep 17 00:00:00 2001 From: Shane C Date: Thu, 4 Jul 2024 16:46:29 -0400 Subject: [PATCH 3/7] testing exit codes --- linux/run.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/linux/run.go b/linux/run.go index f214f2e..722e508 100644 --- a/linux/run.go +++ b/linux/run.go @@ -40,6 +40,7 @@ func (cmd *LinuxCommand) Run() error { if err := command.Start(); err != nil { var exitErr *exec.ExitError if errors.As(err, &exitErr) { + fmt.Println(exitErr.ExitCode()) if exitErr.ExitCode() == 127 { return ErrCommandNotFound } else { @@ -51,6 +52,7 @@ func (cmd *LinuxCommand) Run() error { if err := command.Start(); err != nil { var exitErr *exec.ExitError if errors.As(err, &exitErr) { + fmt.Println(exitErr.ExitCode()) if exitErr.ExitCode() == 127 { return ErrCommandNotFound } else { From c10fdf32b2b0209963c1b3bbf61b2145cfb12daf Mon Sep 17 00:00:00 2001 From: Shane C Date: Thu, 4 Jul 2024 17:14:10 -0400 Subject: [PATCH 4/7] add executable check for commands --- linux/interface.go | 7 ++++--- linux/run.go | 12 +++++++++++- linux/utils.go | 21 +++++++++++++++++++++ main.go | 2 +- test.go | 22 ++++++++++++++++++++++ 5 files changed, 59 insertions(+), 5 deletions(-) create mode 100644 test.go diff --git a/linux/interface.go b/linux/interface.go index 9cac60b..384ef94 100644 --- a/linux/interface.go +++ b/linux/interface.go @@ -19,7 +19,8 @@ type CommandOptions struct { // Errors var ( - ErrFetchingCwd = errors.New("error fetching cwd") - ErrRunningCmd = errors.New("error running command") - ErrCommandNotFound = errors.New("error command not found") + ErrFetchingCwd = errors.New("error fetching cwd") + ErrRunningCmd = errors.New("error running command") + ErrCommandNotFound = errors.New("error command not found") + ErrCommandNotExecutable = errors.New("error command not executable") ) diff --git a/linux/run.go b/linux/run.go index 722e508..2bfa888 100644 --- a/linux/run.go +++ b/linux/run.go @@ -30,6 +30,7 @@ func NewCommand(options CommandOptions) (*LinuxCommand, error) { func (cmd *LinuxCommand) Run() error { command := exec.Command(cmd.Options.Shell, "-c", cmd.Options.Command) + command.Path = cmd.Options.Cwd command.Args = append(command.Args, cmd.Options.Args...) // Loop through env to format and add them to the command. @@ -37,6 +38,15 @@ func (cmd *LinuxCommand) Run() error { command.Env = append(command.Env, fmt.Sprintf("%s=%s", key, value)) } + isCommandExecutable, err := cmd.isCommandExecutable(cmd.Options.Command) + if err != nil { + return err + } + + if !isCommandExecutable { + return ErrCommandNotExecutable + } + if err := command.Start(); err != nil { var exitErr *exec.ExitError if errors.As(err, &exitErr) { @@ -49,7 +59,7 @@ func (cmd *LinuxCommand) Run() error { } } - if err := command.Start(); err != nil { + if err := command.Wait(); err != nil { var exitErr *exec.ExitError if errors.As(err, &exitErr) { fmt.Println(exitErr.ExitCode()) diff --git a/linux/utils.go b/linux/utils.go index dcc5e87..7bc4bc9 100644 --- a/linux/utils.go +++ b/linux/utils.go @@ -3,9 +3,30 @@ package linux import ( "errors" "fmt" + "golang.org/x/sys/unix" + "io/fs" + "os" "os/exec" ) +func (cmd *LinuxCommand) isCommandExecutable(command string) (bool, error) { + + if _, err := os.Stat(command); errors.Is(err, fs.ErrNotExist) { + return false, err + } + + if err := unix.Access(command, unix.X_OK); err != nil { + if !errors.Is(err, unix.EACCES) { + return false, nil + } else { + return false, err + } + } + + return true, nil + +} + func (cmd *LinuxCommand) doesCommandExist(command string) (bool, error) { shellCmd := exec.Command(cmd.Options.Shell, "-c", fmt.Sprintf("command -v %s", command)) diff --git a/main.go b/main.go index 31c1b00..e5b9d97 100644 --- a/main.go +++ b/main.go @@ -1,4 +1,4 @@ -package shell +package main import ( "bytes" diff --git a/test.go b/test.go new file mode 100644 index 0000000..819deec --- /dev/null +++ b/test.go @@ -0,0 +1,22 @@ +package main + +import ( + "git.shadowhosting.xyz/Eggactyl/shell/linux" + "log" +) + +func main() { + + cmd, err := linux.NewCommand(linux.CommandOptions{ + Command: "./test.sh", + }) + + if err != nil { + log.Fatalln(err) + } + + if err := cmd.Run(); err != nil { + log.Fatalln(err) + } + +} From be8fd4ca55b105c4725558f3531c873526788fef Mon Sep 17 00:00:00 2001 From: Shane C Date: Thu, 4 Jul 2024 17:14:44 -0400 Subject: [PATCH 5/7] remove test file --- test.go | 22 ---------------------- 1 file changed, 22 deletions(-) delete mode 100644 test.go diff --git a/test.go b/test.go deleted file mode 100644 index 819deec..0000000 --- a/test.go +++ /dev/null @@ -1,22 +0,0 @@ -package main - -import ( - "git.shadowhosting.xyz/Eggactyl/shell/linux" - "log" -) - -func main() { - - cmd, err := linux.NewCommand(linux.CommandOptions{ - Command: "./test.sh", - }) - - if err != nil { - log.Fatalln(err) - } - - if err := cmd.Run(); err != nil { - log.Fatalln(err) - } - -} From 368b99ecfac0b94725606591dfc096ead538629f Mon Sep 17 00:00:00 2001 From: Shane C Date: Thu, 4 Jul 2024 17:16:13 -0400 Subject: [PATCH 6/7] properly handle error --- linux/run.go | 4 ++-- main.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/linux/run.go b/linux/run.go index 2bfa888..ec90af2 100644 --- a/linux/run.go +++ b/linux/run.go @@ -54,7 +54,7 @@ func (cmd *LinuxCommand) Run() error { if exitErr.ExitCode() == 127 { return ErrCommandNotFound } else { - return fmt.Errorf("%w: %w", ErrRunningCmd, err) + return fmt.Errorf("%s: %w", ErrRunningCmd.Error(), err) } } } @@ -66,7 +66,7 @@ func (cmd *LinuxCommand) Run() error { if exitErr.ExitCode() == 127 { return ErrCommandNotFound } else { - return fmt.Errorf("%w: %w", ErrRunningCmd, err) + return fmt.Errorf("%s: %w", ErrRunningCmd.Error(), err) } } } diff --git a/main.go b/main.go index e5b9d97..31c1b00 100644 --- a/main.go +++ b/main.go @@ -1,4 +1,4 @@ -package main +package shell import ( "bytes" From 942735b7266c3f74cace19a4a83f7014ea0f53cd Mon Sep 17 00:00:00 2001 From: Shane C Date: Thu, 4 Jul 2024 17:27:41 -0400 Subject: [PATCH 7/7] fix permissions error, fix cwd path --- linux/run.go | 2 +- linux/utils.go | 3 ++- main.go | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/linux/run.go b/linux/run.go index ec90af2..8009d16 100644 --- a/linux/run.go +++ b/linux/run.go @@ -30,7 +30,7 @@ func NewCommand(options CommandOptions) (*LinuxCommand, error) { func (cmd *LinuxCommand) Run() error { command := exec.Command(cmd.Options.Shell, "-c", cmd.Options.Command) - command.Path = cmd.Options.Cwd + command.Dir = cmd.Options.Cwd command.Args = append(command.Args, cmd.Options.Args...) // Loop through env to format and add them to the command. diff --git a/linux/utils.go b/linux/utils.go index 7bc4bc9..ba6a1d5 100644 --- a/linux/utils.go +++ b/linux/utils.go @@ -16,9 +16,10 @@ func (cmd *LinuxCommand) isCommandExecutable(command string) (bool, error) { } if err := unix.Access(command, unix.X_OK); err != nil { - if !errors.Is(err, unix.EACCES) { + if err == unix.EACCES { return false, nil } else { + fmt.Println(err) return false, err } } diff --git a/main.go b/main.go index 31c1b00..e5b9d97 100644 --- a/main.go +++ b/main.go @@ -1,4 +1,4 @@ -package shell +package main import ( "bytes"