Browse Source

Merge branch 'feature/standards-compliant' into 'master'

Feature/standards compliant

See merge request !1
Fredric Silberberg 5 years ago
parent
commit
5122c83609
7 changed files with 211 additions and 174 deletions
  1. 1
    1
      Makefile
  2. 28
    4
      common.go
  3. 8
    8
      free.go
  4. 102
    93
      free/main.go
  5. 61
    62
      ls/main.go
  6. 9
    4
      ps/main.go
  7. 2
    2
      utils.go

+ 1
- 1
Makefile View File

@@ -11,7 +11,7 @@ COVER_DIR=cover
11 11
 
12 12
 # Package lists
13 13
 TOPLEVEL_PKG := jsh
14
-CMD_LIST := jsh/ps
14
+CMD_LIST := jsh/ps jsh/free jsh/ls
15 15
 
16 16
 # List building
17 17
 ALL_LIST = $(TOPLEVEL_PKG) $(CMD_LIST)

+ 28
- 4
common.go View File

@@ -4,25 +4,27 @@ package jsh
4 4
 
5 5
 import (
6 6
 	"encoding/json"
7
+	"fmt"
7 8
 )
8 9
 
9
-type JshOutput struct {
10
+type JshFrame struct {
10 11
 	StdOut interface{}
11 12
 	StdErr interface{}
12 13
 }
13 14
 
14 15
 // Size prefixes as integers, using binary representation
15 16
 type Unit int
17
+
16 18
 const (
17
-	B Unit = 2 ^ 0
19
+	B  Unit = 2 ^ 0
18 20
 	KB Unit = 2 ^ 10
19 21
 	MB Unit = 2 ^ 20
20 22
 	GB Unit = 2 ^ 30
21 23
 	TB Unit = 2 ^ 40
22 24
 )
23 25
 
24
-// Converts a Jshoutput into a JSON string
25
-func (j JshOutput) ToJson() *string {
26
+// Converts a JshFrame into a JSON string
27
+func (j JshFrame) ToJson() *string {
26 28
 	jsonOut, err := json.Marshal(j)
27 29
 	if err != nil {
28 30
 		panic(err)
@@ -30,3 +32,25 @@ func (j JshOutput) ToJson() *string {
30 32
 	jsonString := string(jsonOut)
31 33
 	return &jsonString
32 34
 }
35
+
36
+// goroutine for outputing frames. Pass it a channel of pointers to JshFrames,
37
+// and it will send "true" to the done channel once you close the queue channel.
38
+func OutputFrames(queue chan *JshFrame, done chan bool) {
39
+	fmt.Printf("[")
40
+	isFirst := true
41
+	for {
42
+		frame, more := <-queue
43
+		if more {
44
+			if !isFirst {
45
+				fmt.Printf(",")
46
+			} else {
47
+				isFirst = false
48
+			}
49
+			fmt.Printf(*frame.ToJson())
50
+		} else {
51
+			fmt.Printf("]\n")
52
+			done <- true
53
+			return
54
+		}
55
+	}
56
+}

+ 8
- 8
free.go View File

@@ -1,8 +1,8 @@
1
-/* File for free-related structs and methods */
2
-
3
-package jsh
4
-
5
-type MemStat struct {
6
-	Stat int
7
-	Units Unit
8
-}
1
+/* File for free-related structs and methods */
2
+
3
+package jsh
4
+
5
+type MemStat struct {
6
+	Stat  int
7
+	Units Unit
8
+}

+ 102
- 93
free/main.go View File

@@ -1,93 +1,102 @@
1
-package main
2
-
3
-import (
4
-	"bufio"
5
-	"errors"
6
-	"flag"
7
-	"fmt"
8
-	"jsh"
9
-	"regexp"
10
-	"os"
11
-	"strconv"
12
-)
13
-
14
-func convertUnit(stringUnit string) (jsh.Unit, error) {
15
-	switch stringUnit {
16
-	case "B":
17
-		return jsh.B, nil
18
-	case "kB":
19
-		return jsh.KB, nil
20
-	case "mB":
21
-		return jsh.MB, nil
22
-	case "gB":
23
-		return jsh.GB, nil
24
-	case "tB":
25
-		return jsh.TB, nil
26
-	default:
27
-		return 0, errors.New(fmt.Sprintln("Unknown unit %s", stringUnit))
28
-	}
29
-}
30
-
31
-func parseLine(line string) (string, jsh.MemStat, error) {
32
-	// Recognizes a alphanumeric or () word, the : character, whitespace, the number we're looking for,
33
-	// more whitespace, and possibly the unit
34
-	lineRegex := regexp.MustCompile("(?P<key>^[\\w()]+):\\s+(?P<val>\\d+)(\\s+)?(?P<unit>\\w+)?")
35
-	
36
-	// Parse the line, and construct a map of the valid matches
37
-	parsedLine := lineRegex.FindStringSubmatch(line)
38
-	names := lineRegex.SubexpNames()
39
-	matchedVals := map[string]string{}
40
-	for i, n := range parsedLine {
41
-		matchedVals[names[i]] = n
42
-	}
43
-
44
-	key := matchedVals["key"]
45
-	val, err := strconv.Atoi(matchedVals["val"])
46
-	if err != nil {
47
-		return "", jsh.MemStat{}, err
48
-	}
49
-	unit, err := convertUnit(matchedVals["unit"])
50
-	if err != nil {
51
-		return "", jsh.MemStat{}, err
52
-	}
53
-	return key, jsh.MemStat{val, unit}, nil
54
-}
55
-
56
-func parseMemInfo() jsh.JshOutput {
57
-	file, err := os.Open("/proc/meminfo")
58
-	if err != nil {
59
-		return jsh.JshOutput{[]string{}, []error{err}}
60
-	}
61
-	defer file.Close()
62
-
63
-	scanner := bufio.NewScanner(file)
64
-	memInfo := make(map[string]jsh.MemStat)
65
-	errors := []error{}
66
-	// Read in each line of the meminfo file, and place it in the map
67
-	for scanner.Scan() {
68
-		key, val, err := parseLine(scanner.Text())
69
-		if err != nil {
70
-			errors = append(errors, err)
71
-		}
72
-		memInfo[key] = val
73
-	}
74
-	
75
-	finalOut := jsh.JshOutput{memInfo, errors}
76
-	return finalOut
77
-}
78
-
79
-func runJsonMode() {
80
-	output := parseMemInfo()
81
-	fmt.Println("%s", *output.ToJson())
82
-}
83
-
84
-func main() {
85
-	jsonModePtr := flag.Bool("json", false, "whether to use json mode for output")
86
-	flag.Parse()
87
-
88
-	if !*jsonModePtr {
89
-		fmt.Printf("%s", jsh.Fallback("/usr/bin/free"))
90
-	} else {
91
-		runJsonMode()
92
-	}
93
-}
1
+package main
2
+
3
+import (
4
+	"bufio"
5
+	"errors"
6
+	"flag"
7
+	"fmt"
8
+	"jsh"
9
+	"os"
10
+	"regexp"
11
+	"strconv"
12
+)
13
+
14
+func convertUnit(stringUnit string) (jsh.Unit, error) {
15
+	switch stringUnit {
16
+	case "B":
17
+		return jsh.B, nil
18
+	case "kB":
19
+		return jsh.KB, nil
20
+	case "mB":
21
+		return jsh.MB, nil
22
+	case "gB":
23
+		return jsh.GB, nil
24
+	case "tB":
25
+		return jsh.TB, nil
26
+	case "":
27
+		return jsh.B, nil
28
+	default:
29
+		return 0, errors.New(fmt.Sprintf("Unknown unit: %s\n", stringUnit))
30
+	}
31
+}
32
+
33
+func parseLine(line string) (string, jsh.MemStat, error) {
34
+	// Recognizes a alphanumeric or () word, the : character, whitespace, the number we're looking for,
35
+	// more whitespace, and possibly the unit
36
+	lineRegex := regexp.MustCompile("(?P<key>^[\\w()]+):\\s+(?P<val>\\d+)(\\s+)?(?P<unit>\\w+)?")
37
+
38
+	// Parse the line, and construct a map of the valid matches
39
+	parsedLine := lineRegex.FindStringSubmatch(line)
40
+	names := lineRegex.SubexpNames()
41
+	matchedVals := map[string]string{}
42
+	for i, n := range parsedLine {
43
+		matchedVals[names[i]] = n
44
+	}
45
+
46
+	key := matchedVals["key"]
47
+	val, err := strconv.Atoi(matchedVals["val"])
48
+	if err != nil {
49
+		return "", jsh.MemStat{}, err
50
+	}
51
+	unit, err := convertUnit(matchedVals["unit"])
52
+	if err != nil {
53
+		return "", jsh.MemStat{}, err
54
+	}
55
+	return key, jsh.MemStat{val, unit}, nil
56
+}
57
+
58
+func parseMemInfo() jsh.JshFrame {
59
+	file, err := os.Open("/proc/meminfo")
60
+	if err != nil {
61
+		return jsh.JshFrame{[]string{}, []error{err}}
62
+	}
63
+	defer file.Close()
64
+
65
+	scanner := bufio.NewScanner(file)
66
+	memInfo := make(map[string]jsh.MemStat)
67
+	errors := []error{}
68
+	// Read in each line of the meminfo file, and place it in the map
69
+	for scanner.Scan() {
70
+		key, val, err := parseLine(scanner.Text())
71
+		if err != nil {
72
+			errors = append(errors, err)
73
+		}
74
+		memInfo[key] = val
75
+	}
76
+
77
+	// Wrap with array
78
+	stdOut := []map[string]jsh.MemStat{memInfo}
79
+	finalOut := jsh.JshFrame{stdOut, errors}
80
+	return finalOut
81
+}
82
+
83
+func runJsonMode() {
84
+	output := parseMemInfo()
85
+	queue := make(chan *jsh.JshFrame)
86
+	done := make(chan bool)
87
+	go jsh.OutputFrames(queue, done)
88
+	queue <- &output
89
+	close(queue)
90
+	<-done
91
+}
92
+
93
+func main() {
94
+	jsonModePtr := flag.Bool("json", false, "whether to use json mode for output")
95
+	flag.Parse()
96
+
97
+	if !*jsonModePtr {
98
+		fmt.Printf("%s", jsh.Fallback("/usr/bin/free"))
99
+	} else {
100
+		runJsonMode()
101
+	}
102
+}

+ 61
- 62
ls/main.go View File

@@ -1,76 +1,75 @@
1 1
 package main
2 2
 
3 3
 import (
4
-  "io/ioutil"
5
-  "fmt"
6
-  "flag"
7
-  "log"
8
-  "syscall"
9
-  "strconv"
4
+	"flag"
5
+	"fmt"
6
+	"io/ioutil"
7
+	"log"
8
+	"strconv"
9
+	"syscall"
10 10
 )
11 11
 
12
-
13
-func get_fileinfo(f string, size bool, mode bool, inode bool) string{
14
-  var stat syscall.Stat_t
15
-  var ret string 
16
-  ret = "{\"name\":\"" + f + "\""
17
-  if err := syscall.Stat(f, &stat); err != nil {
18
-    log.Fatal(err)
19
-  }
20
-  if(size){
21
-    ret = ret + ", \"size\":" + strconv.FormatInt(stat.Size,10)
22
-  }
23
-  if(mode){
24
-    ret = ret + ", \"mode\":" + strconv.Itoa(int(stat.Mode))
25
-  }
26
-  if(inode){
27
-    ret = ret + ", \"inode\":" + strconv.FormatUint(stat.Ino,10)
28
-  }
29
-  ret = ret + "}"
30
-  return ret 
12
+func get_fileinfo(f string, size bool, mode bool, inode bool) string {
13
+	var stat syscall.Stat_t
14
+	var ret string
15
+	ret = "{\"files\": [{\"name\":\"" + f + "\""
16
+	if err := syscall.Stat(f, &stat); err != nil {
17
+		log.Fatal(err)
18
+	}
19
+	if size {
20
+		ret = ret + ", \"size\":" + strconv.FormatInt(stat.Size, 10)
21
+	}
22
+	if mode {
23
+		ret = ret + ", \"mode\":" + strconv.Itoa(int(stat.Mode))
24
+	}
25
+	if inode {
26
+		ret = ret + ", \"inode\":" + strconv.FormatUint(stat.Ino, 10)
27
+	}
28
+	ret = ret + "}]}"
29
+	return ret
31 30
 }
32 31
 
33 32
 func main() {
34
-  // here be the ls flags
33
+	// here be the ls flags
35 34
 
36
-  var a_flag bool                      // all files, even ones starting with .
37
-  var mode_flag bool                   // flags
38
-  var inode_flag bool		       // inode
39
-  var size_flag	bool		       // size
40
-  var first = true
35
+	var a_flag bool     // all files, even ones starting with .
36
+	var mode_flag bool  // flags
37
+	var inode_flag bool // inode
38
+	var size_flag bool  // size
39
+	var first = true
41 40
 
42
-  flag.BoolVar(&a_flag, "a", false, "lists all files in directory, even hidden ones")
43
-  flag.BoolVar(&mode_flag, "f", false, "include flags for file")  
44
-  flag.BoolVar(&inode_flag, "i", false, "include flags for file")  
45
-  flag.BoolVar(&size_flag, "s", false, "include flags for file")  
46
-  // end ls flag
41
+	flag.BoolVar(&a_flag, "a", false, "lists all files in directory, even hidden ones")
42
+	flag.BoolVar(&mode_flag, "f", false, "include flags for file")
43
+	flag.BoolVar(&inode_flag, "i", false, "include flags for file")
44
+	flag.BoolVar(&size_flag, "s", false, "include flags for file")
45
+	// end ls flag
47 46
 
48
-  flag.Parse()
49
-  root := "."//flag.Arg(0)
50
-  dir,_ := ioutil.ReadDir(root)
47
+	flag.Parse()
48
+	root := "." //flag.Arg(0)
49
+	dir, _ := ioutil.ReadDir(root)
51 50
 
52
-  fmt.Printf("[\n")
53
-  
54
-  if(!a_flag){
55
-    for _,entry := range dir{
56
-      if(entry.Name()[0]!='.'){
57
-        if(!first){
58
-          fmt.Printf(",")
59
-        }else{
60
-          first = false
61
-	}
62
-        fmt.Printf("%s\n", get_fileinfo(entry.Name(), size_flag, mode_flag, inode_flag))
63
-      }  
64
-    }
65
-  }else{
66
-    for _,entry := range dir{
67
-        if(!first){
68
-          fmt.Printf(",")
69
-        }else{
70
-          first = false
51
+	fmt.Printf("[{\"StdOut\": [\n")
52
+
53
+	if !a_flag {
54
+		for _, entry := range dir {
55
+			if entry.Name()[0] != '.' {
56
+				if !first {
57
+					fmt.Printf(",")
58
+				} else {
59
+					first = false
60
+				}
61
+				fmt.Printf("%s\n", get_fileinfo(entry.Name(), size_flag, mode_flag, inode_flag))
62
+			}
63
+		}
64
+	} else {
65
+		for _, entry := range dir {
66
+			if !first {
67
+				fmt.Printf(",")
68
+			} else {
69
+				first = false
70
+			}
71
+			fmt.Printf("%s\n", get_fileinfo(entry.Name(), size_flag, mode_flag, inode_flag))
72
+		}
71 73
 	}
72
-        fmt.Printf("%s\n", get_fileinfo(entry.Name(), size_flag, mode_flag, inode_flag))
73
-    }
74
-  }
75
-  fmt.Printf("]\n")
74
+	fmt.Printf("], \"StdErr\": []}]\n")
76 75
 }

+ 9
- 4
ps/main.go View File

@@ -25,11 +25,16 @@ func PsOutputToProcesses(out string) *[]jsh.Process {
25 25
 
26 26
 func runJsonMode() {
27 27
 	// Run procps-ng "ps" with full output
28
-	psOut := string(*jsh.FallbackWithArgs("/usr/bin/ps",  []string{"auxww"}))
29
-
28
+	psOut := string(*jsh.FallbackWithArgs("/usr/bin/ps", []string{"auxww"}))
30 29
 	processesPtr := PsOutputToProcesses(psOut)
31
-	finalOut := jsh.JshOutput{*processesPtr, []string{}}
32
-	fmt.Printf("%s", *finalOut.ToJson())
30
+	frame := jsh.JshFrame{*processesPtr, []string{}}
31
+
32
+	queue := make(chan *jsh.JshFrame)
33
+	done := make(chan bool)
34
+	go jsh.OutputFrames(queue, done)
35
+	queue <- &frame
36
+	close(queue)
37
+	<-done
33 38
 }
34 39
 
35 40
 func main() {

+ 2
- 2
utils.go View File

@@ -2,9 +2,9 @@ package jsh
2 2
 
3 3
 import (
4 4
 	"math"
5
-	"unicode"
6 5
 	"os"
7 6
 	"os/exec"
7
+	"unicode"
8 8
 )
9 9
 
10 10
 // FieldsN slices s into substrings after each instance of a whitespace
@@ -56,7 +56,7 @@ func FallbackWithArgs(program string, args []string) *[]byte {
56 56
 	if err != nil {
57 57
 		panic(err)
58 58
 	}
59
-	return &out	
59
+	return &out
60 60
 }
61 61
 
62 62
 func Fallback(program string) *[]byte {

Loading…
Cancel
Save