This repository has been archived on 2015-04-29. You can view files and clone it, but cannot push or open issues or pull requests.
jsh/free/main.go
Fredric Silberberg f21df51bd2 Added the PATH searching algorithm we talked about at the last meeting with Ciaraldi. It will find the location of our program
and search the PATH for that location. If found, it will search all remaining elements for the requested program. If the location
is not found on the PATH, then it will search the entire PATH for the requested program. If found, it returns the absolute path
to the program. If not, err.
2014-09-24 23:32:11 -04:00

103 lines
2.3 KiB
Go

package main
import (
"bufio"
"errors"
"flag"
"fmt"
"jsh"
"os"
"regexp"
"strconv"
)
func ConvertUnit(stringUnit string) (jsh.Unit, error) {
switch stringUnit {
case "B":
return jsh.B, nil
case "kB":
return jsh.KB, nil
case "mB":
return jsh.MB, nil
case "gB":
return jsh.GB, nil
case "tB":
return jsh.TB, nil
case "": // On some systems (Arch, for example) bytes are just the empty string
return jsh.B, nil
default:
return 0, errors.New(fmt.Sprintf("Unknown unit: %s\n", stringUnit))
}
}
func ParseLine(line string) (string, jsh.MemStat, error) {
// Recognizes a alphanumeric or () word, the : character, whitespace, the number we're looking for,
// more whitespace, and possibly the unit
lineRegex := regexp.MustCompile("(?P<key>^[\\w()]+):\\s+(?P<val>\\d+)(\\s+)?(?P<unit>\\w+)?")
// Parse the line, and construct a map of the valid matches
parsedLine := lineRegex.FindStringSubmatch(line)
names := lineRegex.SubexpNames()
matchedVals := map[string]string{}
for i, n := range parsedLine {
matchedVals[names[i]] = n
}
key := matchedVals["key"]
val, err := strconv.Atoi(matchedVals["val"])
if err != nil {
return "", jsh.MemStat{}, err
}
unit, err := ConvertUnit(matchedVals["unit"])
if err != nil {
return "", jsh.MemStat{}, err
}
return key, jsh.MemStat{val, unit}, nil
}
func parseMemInfo() jsh.JshFrame {
file, err := os.Open("/proc/meminfo")
if err != nil {
return jsh.JshFrame{[]string{}, []error{err}}
}
defer file.Close()
scanner := bufio.NewScanner(file)
memInfo := make(map[string]jsh.MemStat)
errors := []error{}
// Read in each line of the meminfo file, and place it in the map
for scanner.Scan() {
key, val, err := ParseLine(scanner.Text())
if err != nil {
errors = append(errors, err)
}
memInfo[key] = val
}
// Wrap with array
stdOut := []map[string]jsh.MemStat{memInfo}
finalOut := jsh.JshFrame{stdOut, errors}
return finalOut
}
func runJsonMode() {
output := parseMemInfo()
queue := make(chan *jsh.JshFrame)
done := make(chan bool)
go jsh.OutputFrames(queue, done)
queue <- &output
close(queue)
<-done
}
func main() {
jsonModePtr := flag.Bool("json", false, "whether to use json mode for output")
flag.Parse()
if !*jsonModePtr {
fmt.Printf("%s", jsh.Fallback("free"))
} else {
runJsonMode()
}
}