Merge branch 'feature/path-search' into 'master'
Feature/path search Added the PATH searching algorithm that we talked about at the last meeting with Ciaraldi. We'll need to update ls to follow the same flag standards that we are. See merge request !4
This commit is contained in:
commit
b6b7cb023e
@ -95,7 +95,7 @@ func main() {
|
|||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
if !*jsonModePtr {
|
if !*jsonModePtr {
|
||||||
fmt.Printf("%s", jsh.Fallback("/usr/bin/free"))
|
fmt.Printf("%s", jsh.Fallback("free"))
|
||||||
} else {
|
} else {
|
||||||
runJsonMode()
|
runJsonMode()
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,8 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"jsh"
|
"jsh"
|
||||||
"testing"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func testUnitError(expected jsh.Unit, t *testing.T) {
|
func testUnitError(expected jsh.Unit, t *testing.T) {
|
||||||
@ -45,14 +45,14 @@ func TestConvertBadUnit(t *testing.T) {
|
|||||||
|
|
||||||
func TestParseGoodLine(t *testing.T) {
|
func TestParseGoodLine(t *testing.T) {
|
||||||
goodLine := "MemTotal: 16370344 kB"
|
goodLine := "MemTotal: 16370344 kB"
|
||||||
expectedStat := jsh.MemStat { 16370344, jsh.KB }
|
expectedStat := jsh.MemStat{16370344, jsh.KB}
|
||||||
expectedKey := "MemTotal"
|
expectedKey := "MemTotal"
|
||||||
key, stat, err := ParseLine(goodLine)
|
key, stat, err := ParseLine(goodLine)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
if key != expectedKey {
|
if key != expectedKey {
|
||||||
t.Errorf("Expected key %s, got key %s", expectedKey, key)
|
t.Errorf("Expected key %s, got key %s", expectedKey, key)
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(expectedStat, stat) {
|
if !reflect.DeepEqual(expectedStat, stat) {
|
||||||
t.Error("Expected stat ", expectedStat, " got ", stat)
|
t.Error("Expected stat ", expectedStat, " got ", stat)
|
||||||
|
@ -25,7 +25,7 @@ func PsOutputToProcesses(out string) *[]jsh.Process {
|
|||||||
|
|
||||||
func runJsonMode() {
|
func runJsonMode() {
|
||||||
// Run procps-ng "ps" with full output
|
// Run procps-ng "ps" with full output
|
||||||
psOut := string(*jsh.FallbackWithArgs("/usr/bin/ps", []string{"auxww"}))
|
psOut := string(*jsh.FallbackWithArgs("ps", []string{"auxww"}))
|
||||||
processesPtr := PsOutputToProcesses(psOut)
|
processesPtr := PsOutputToProcesses(psOut)
|
||||||
frame := jsh.JshFrame{*processesPtr, []string{}}
|
frame := jsh.JshFrame{*processesPtr, []string{}}
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ func main() {
|
|||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
if !*jsonModePtr {
|
if !*jsonModePtr {
|
||||||
fmt.Printf("%s", jsh.Fallback("/usr/bin/ps"))
|
fmt.Printf("%s", jsh.Fallback("ps"))
|
||||||
} else {
|
} else {
|
||||||
runJsonMode()
|
runJsonMode()
|
||||||
}
|
}
|
||||||
|
66
utils.go
66
utils.go
@ -1,9 +1,12 @@
|
|||||||
package jsh
|
package jsh
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"strings"
|
||||||
"unicode"
|
"unicode"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -52,7 +55,13 @@ func FallbackWithArgs(program string, args []string) *[]byte {
|
|||||||
if args == nil {
|
if args == nil {
|
||||||
args = os.Args[1:]
|
args = os.Args[1:]
|
||||||
}
|
}
|
||||||
out, err := exec.Command(program, args...).Output()
|
executable, err := findExecutable(program)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
out, err := exec.Command(executable, args...).Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -62,3 +71,58 @@ func FallbackWithArgs(program string, args []string) *[]byte {
|
|||||||
func Fallback(program string) *[]byte {
|
func Fallback(program string) *[]byte {
|
||||||
return FallbackWithArgs(program, nil)
|
return FallbackWithArgs(program, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Finds a given executable on the system path, returning the absolute path the program if found, and an error
|
||||||
|
// if it's not found
|
||||||
|
func findExecutable(programName string) (string, error) {
|
||||||
|
// First, find our binary location
|
||||||
|
binLocWithName, err := os.Readlink("/proc/self/exe")
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
// Get our binary name and remove it from the binary path, leaving just our binary location
|
||||||
|
// Also trim the extra path separator
|
||||||
|
binName := os.Args[0]
|
||||||
|
binLoc := strings.TrimSuffix(binLocWithName, binName)
|
||||||
|
binLoc = strings.TrimSuffix(binLoc, string(os.PathSeparator))
|
||||||
|
|
||||||
|
// Get the system path and split it by the system path separator
|
||||||
|
pathString := os.Getenv("PATH")
|
||||||
|
path := strings.Split(pathString, string(os.PathListSeparator))
|
||||||
|
|
||||||
|
// Loop until we find our location on the path, so we know where to start looking after for the
|
||||||
|
// next implementation of the given program name
|
||||||
|
var foundPath bool
|
||||||
|
var pathNum int
|
||||||
|
for index, pathEl := range path {
|
||||||
|
// Trim the path separator from this element, if it has it
|
||||||
|
pathEl = strings.TrimSuffix(pathEl, string(os.PathSeparator))
|
||||||
|
if pathEl == binLoc {
|
||||||
|
foundPath = true
|
||||||
|
pathNum = index
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we found our path on the real path, then search the remaining path elements. Otherwise, search all elements
|
||||||
|
if foundPath {
|
||||||
|
return searchPath(programName, path[pathNum+1:len(path)-1])
|
||||||
|
} else {
|
||||||
|
return searchPath(programName, path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Searches the given set of paths for a the given program, returing when it finds it or returning an error if the
|
||||||
|
// program is not found
|
||||||
|
func searchPath(programName string, path []string) (string, error) {
|
||||||
|
// Loop through each path element, test for the existance of the file, and then return if we find it
|
||||||
|
for _, pathEl := range path {
|
||||||
|
fullProgram := pathEl + string(os.PathSeparator) + programName
|
||||||
|
_, err := os.Stat(fullProgram)
|
||||||
|
if err == nil {
|
||||||
|
return fullProgram, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", errors.New(fmt.Sprintf("Could not find program %s on the PATH: %s", programName, path))
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user