mirror of
https://github.com/gechandesu/runcmd.git
synced 2026-01-23 23:04:13 +03:00
79 lines
2.3 KiB
V
79 lines
2.3 KiB
V
module runcmd
|
|
|
|
import context
|
|
import os
|
|
|
|
// new creates new command with given command name and arguments.
|
|
pub fn new(name string, arg ...string) &Command {
|
|
return &Command{
|
|
path: name
|
|
args: arg
|
|
}
|
|
}
|
|
|
|
// with_context creates new command with context, command name and arguments.
|
|
pub fn with_context(ctx context.Context, name string, arg ...string) &Command {
|
|
mut cmd := new(name, ...arg)
|
|
cmd.ctx = ctx
|
|
cmd.cancel = fn [mut cmd] () ! {
|
|
if cmd.process != none {
|
|
cmd.process.signal(.term)!
|
|
}
|
|
}
|
|
return cmd
|
|
}
|
|
|
|
// is_present returns true if cmd is present on system. cmd may be a command
|
|
// name or filepath (relative or absolute).
|
|
// The result relies on `look_path()` output, see its docs for command search
|
|
// details.
|
|
pub fn is_present(cmd string) bool {
|
|
_ := look_path(cmd) or { return false }
|
|
return true
|
|
}
|
|
|
|
// look_path returns the absolute path to executable file. cmd may be a command
|
|
// name or filepath (relative or absolute). The command is searched in PATH. If
|
|
// the name contains a slash, then the PATH search is not performed, instead the
|
|
// path will be resolved and the file existence will be checked. In both cases
|
|
// the file must have the execute permission bit enabled.
|
|
// Note: To use executables located in the current working directory use './file'
|
|
// instead of just 'file'. Searching for executable files in the current directory
|
|
// is disabled for security reasons. See https://go.dev/blog/path-security.
|
|
pub fn look_path(cmd string) !string {
|
|
if cmd.is_blank() {
|
|
return os.ExecutableNotFoundError{}
|
|
}
|
|
|
|
// Do not search executable in PATH if its name contains a slashes (as POSIX-shells does),
|
|
// See PATH in: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03
|
|
|
|
if cmd.contains('/') {
|
|
actual_path := os.abs_path(os.expand_tilde_to_home(os.norm_path(cmd)))
|
|
if is_executable_file(actual_path) {
|
|
return actual_path
|
|
} else {
|
|
return os.ExecutableNotFoundError{}
|
|
}
|
|
}
|
|
|
|
paths := os.getenv('PATH').split(os.path_delimiter)
|
|
|
|
for path in paths {
|
|
if path in ['', '.'] {
|
|
// Prohibit current directory.
|
|
continue
|
|
}
|
|
actual_path := os.abs_path(os.join_path_single(path, cmd))
|
|
if is_executable_file(actual_path) {
|
|
return actual_path
|
|
}
|
|
}
|
|
|
|
return os.ExecutableNotFoundError{}
|
|
}
|
|
|
|
fn is_executable_file(file string) bool {
|
|
return os.is_file(file) && os.is_executable(file)
|
|
}
|