go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers/os/resources/command.go (about) 1 // Copyright (c) Mondoo, Inc. 2 // SPDX-License-Identifier: BUSL-1.1 3 4 package resources 5 6 import ( 7 "errors" 8 "io" 9 "sync" 10 11 "go.mondoo.com/cnquery/llx" 12 "go.mondoo.com/cnquery/providers-sdk/v1/plugin" 13 "go.mondoo.com/cnquery/providers/os/connection/shared" 14 ) 15 16 type mqlCommandInternal struct { 17 lock sync.Mutex 18 commandIsRunning bool 19 } 20 21 func (c *mqlCommand) id() (string, error) { 22 return c.Command.Data, c.Command.Error 23 } 24 25 func (c *mqlCommand) execute(cmd string) error { 26 c.lock.Lock() 27 if c.commandIsRunning { 28 c.lock.Unlock() 29 return plugin.NotReady 30 } 31 c.commandIsRunning = true 32 c.lock.Unlock() 33 34 x, err := c.MqlRuntime.Connection.(shared.Connection).RunCommand(cmd) 35 if err != nil { 36 c.Exitcode = plugin.TValue[int64]{Error: err, State: plugin.StateIsSet} 37 c.Stdout = plugin.TValue[string]{Error: err, State: plugin.StateIsSet} 38 c.Stderr = plugin.TValue[string]{Error: err, State: plugin.StateIsSet} 39 return err 40 } 41 42 c.Exitcode = plugin.TValue[int64]{Data: int64(x.ExitStatus), State: plugin.StateIsSet} 43 44 stdout, err := io.ReadAll(x.Stdout) 45 c.Stdout = plugin.TValue[string]{Data: string(stdout), Error: err, State: plugin.StateIsSet} 46 47 stderr, err := io.ReadAll(x.Stderr) 48 c.Stderr = plugin.TValue[string]{Data: string(stderr), Error: err, State: plugin.StateIsSet} 49 50 c.lock.Lock() 51 c.commandIsRunning = false 52 c.lock.Unlock() 53 54 return nil 55 } 56 57 func (c *mqlCommand) stdout(cmd string) (string, error) { 58 // note: we ignore the return value because everything is set in execute 59 return "", c.execute(cmd) 60 } 61 62 func (c *mqlCommand) stderr(cmd string) (string, error) { 63 // note: we ignore the return value because everything is set in execute 64 return "", c.execute(cmd) 65 } 66 67 func (c *mqlCommand) exitcode(cmd string) (int64, error) { 68 // note: we ignore the return value because everything is set in execute 69 return 0, c.execute(cmd) 70 } 71 72 func runCommand(runtime *plugin.Runtime, cmd string) (string, error) { 73 o, err := CreateResource(runtime, "command", map[string]*llx.RawData{ 74 "command": llx.StringData(cmd), 75 }) 76 if err != nil { 77 return "", err 78 } 79 80 command := o.(*mqlCommand) 81 exit := command.GetExitcode() 82 if exit.Error != nil { 83 return "", exit.Error 84 } 85 if exit.Data != 0 { 86 err := command.GetStderr() 87 if err.Error != nil { 88 return "", err.Error 89 } 90 return "", errors.New(err.Data) 91 } 92 93 out := command.GetStdout() 94 if out.Error != nil { 95 return "", out.Error 96 } 97 return out.Data, nil 98 }