diff --git a/df/main.go b/df/main.go new file mode 100644 index 0000000..effe3ab --- /dev/null +++ b/df/main.go @@ -0,0 +1,53 @@ +package main + +import ( + "flag" + "fmt" + "jsh" + "strings" +) + +// Converts raw output of "ps" into a slice of Filesystem objects +func DfOutputToFilesystems(out string) *[]jsh.Filesystem { + filesystems := []jsh.Filesystem{} + lines := strings.Split(out, "\n") + header, fses := lines[0], lines[1:] + numFields := len(strings.Fields(header)) + + for _, fs := range fses { + allFields := jsh.FieldsN(fs, numFields) + if len(allFields) != 0 { + fields := append(allFields[0:4], allFields[5]) + p, err := jsh.NewFilesystem(fields) + if err == nil { + filesystems = append(filesystems, *p) + } + } + } + return &filesystems +} + +func runJsonMode() { + dfOut := string(*jsh.FallbackWithArgs("df", []string{"-B1"})) + filesystemsPtr := DfOutputToFilesystems(dfOut) + frame := jsh.JshFrame{*filesystemsPtr, []string{}} + + queue := make(chan *jsh.JshFrame) + done := make(chan bool) + go jsh.OutputFrames(queue, done) + queue <- &frame + close(queue) + <-done +} + +func main() { + // Parse for JSON flag. + jsonModePtr := flag.Bool("json", false, "a bool") + flag.Parse() + + if !*jsonModePtr { + fmt.Printf("%s", jsh.Fallback("df")) + } else { + runJsonMode() + } +} diff --git a/df/main_test.go b/df/main_test.go new file mode 100644 index 0000000..003cd8c --- /dev/null +++ b/df/main_test.go @@ -0,0 +1,22 @@ +package main + +import ( + "jsh" + "reflect" + "testing" +) + +func TestPsOutputToProcesses(t *testing.T) { + psOutput := `USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND +root 1 0.0 0.1 26204 4916 ? Ss 00:39 0:00 /sbin/init +root 2 0.0 0.0 0 0 ? S 00:39 0:00 [kthreadd]` + processes := PsOutputToProcesses(psOutput) + expected := []jsh.Process{jsh.Process{"root", "1", "0.0", "0.1", "26204", + "4916", "?", "Ss", "00:39", "0:00", "/sbin/init"}, + jsh.Process{"root", "2", "0.0", "0.0", "0", "0", "?", "S", "00:39", + "0:00", "[kthreadd]"}} + actual := *processes + if !reflect.DeepEqual(expected, actual) { + t.Errorf("Processes not parsed correctly.\n%s != %s", expected, actual) + } +} diff --git a/filesystem.go b/filesystem.go new file mode 100644 index 0000000..728827a --- /dev/null +++ b/filesystem.go @@ -0,0 +1,35 @@ +/* File for Filesystem-related structs and methods */ + +package jsh + +import ( + "errors" + "strconv" +) + +// Filesystem is a struct for marshalling into JSON output for the df utility. +type Filesystem struct { + Name string + Size int + Used int + Available int + MountPoint string +} + +// NewFilesystem +func NewFilesystem(args []string) (procPtr *Filesystem, err error) { + err = nil + // 11 = number of fields in the Filesystem struct + if len(args) != 5 { + procPtr = &Filesystem{} + err = errors.New("Unexpected number of columns") + } else { + // TODO: add error checking + size, _ := strconv.Atoi(args[1]) + used, _ := strconv.Atoi(args[2]) + available, _ := strconv.Atoi(args[2]) + procPtr = &Filesystem{ + args[0], size, used, available, args[4]} + } + return +} diff --git a/filesystem_test.go b/filesystem_test.go new file mode 100644 index 0000000..dfa7ecb --- /dev/null +++ b/filesystem_test.go @@ -0,0 +1,28 @@ +package jsh + +import "testing" + +func TestNewFilesystem(t *testing.T) { + tooManyArgs := []string{"1", "2", "3", "4"} + _, err := NewFilesystem(tooManyArgs) + if err == nil { + t.Errorf("Passing 4 strings should raise an error") + } + + tooFewArgs := []string{"1", "2", "3", "4", "5", "6"} + _, err = NewFilesystem(tooFewArgs) + if err == nil { + t.Errorf("Passing 6 strings should raise an error") + } + + justRightArgs := []string{"1", "2", "3", "4", "5"} + proc, err := NewFilesystem(justRightArgs) + if err != nil { + t.Errorf("Passing 5 strings should not raise an error") + } + expected := Filesystem{"1", "2", "3", "4", "5"} + actual := *proc + if expected != actual { + t.Errorf("Filesystem was incorrectly generated:\n%s != %s", expected, actual) + } +}