From 593a8ef24e917f99e02909fdb0d84d3e4916db91 Mon Sep 17 00:00:00 2001 From: Andinus Date: Fri, 17 Apr 2020 18:41:09 +0530 Subject: Update to lynx v0.4.0 --- main.go | 187 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 main.go (limited to 'main.go') diff --git a/main.go b/main.go new file mode 100644 index 0000000..13971e7 --- /dev/null +++ b/main.go @@ -0,0 +1,187 @@ +package main + +import ( + "bufio" + "fmt" + "os" + + "tildegit.org/andinus/grus/lexical" + "tildegit.org/andinus/lynx" +) + +func main() { + initGrus() + + if len(os.Args) == 1 { + fmt.Println("Usage: grus ") + os.Exit(1) + } + + version := "v0.3.1" + + // Print version if first argument is version. + if os.Args[1] == "version" { + fmt.Printf("Grus %s\n", version) + os.Exit(0) + } + + // Define default environment variables. + envVar := make(map[string]bool) + envVar["GRUS_SEARCH_ALL"] = false + envVar["GRUS_ANAGRAMS"] = true + envVar["GRUS_STRICT_UNJUMBLE"] = false + envVar["GRUS_PRINT_PATH"] = false + + // Check environment variables. + for k, _ := range envVar { + env := os.Getenv(k) + if env == "false" || + env == "0" { + envVar[k] = false + } else if env == "true" || + env == "1" { + envVar[k] = true + } + } + + // Print environment variables if first argument is env. + if os.Args[1] == "env" { + for k, v := range envVar { + fmt.Printf("%s: %t\n", k, v) + } + os.Exit(0) + } + + // Define default dictionaries. + dicts := []string{ + "/usr/local/share/dict/words", + "/usr/local/share/dict/web2", + "/usr/share/dict/words", + "/usr/share/dict/web2", + "/usr/share/dict/special/4bsd", + "/usr/share/dict/special/math", + } + + // User has specified dictionaries, prepend them to dicts + // list. + if len(os.Args) >= 3 { + dicts = append(os.Args[2:], dicts...) + } + + // We use this to record if the word was unjumbled. + unjumbled := false + + for k, dict := range dicts { + if _, err := os.Stat(dict); err != nil && + !os.IsNotExist(err) { + // Error is not nil & also it's not path + // doesn't exist error. We do it this way to + // avoid another level of indentation. + panic(err) + } else if err != nil && + os.IsNotExist(err) { + // If file doesn't exist then continue with + // next dictionary. + continue + } + + // Print path to dictionary if printPath is true. + if envVar["GRUS_PRINT_PATH"] { + if k != 0 { + fmt.Println() + } + fmt.Println(dict) + } + + file, err := os.Open(dict) + panicOnErr(err) + + scanner := bufio.NewScanner(file) + for scanner.Scan() { + // Filter words by comparing length first & + // run lexical.Sort on it only if the length + // is equal. + if len(scanner.Text()) == len(os.Args[1]) && + lexical.Sort(scanner.Text()) == lexical.Sort(os.Args[1]) { + fmt.Println(scanner.Text()) + // If the user doesn't want anagrams + // then exit the program. + if !envVar["GRUS_ANAGRAMS"] { + os.Exit(0) + } + unjumbled = true + } + } + panicOnErr(scanner.Err()) + file.Close() + + // If the user has asked to strictly unjumble then we + // cannot exit till it's unjumbled. + if envVar["GRUS_STRICT_UNJUMBLE"] && + !unjumbled { + // If user has asked to strictly unjumble & we + // haven't done that yet & this is the last + // dictionary then we've failed to unjumble it + // & the program must exit with a non-zero + // exit code. + if k == len(dicts)-1 { + os.Exit(1) + } + + // Cannot exit, must search next dictionary. + continue + } + + // If user hasn't asked to search all dictionaries + // then exit the program. + if !envVar["GRUS_SEARCH_ALL"] { + os.Exit(0) + } + } +} + +func initGrus() { + // We need less permissions on these conditions. + if len(os.Args) == 1 || + os.Args[1] == "version" || + os.Args[1] == "env" { + err := lynx.PledgePromises("stdio") + panicOnErr(err) + } else { + err := lynx.PledgePromises("unveil stdio rpath") + panicOnErr(err) + + unveil() + + // Drop unveil from promises. + err = lynx.PledgePromises("stdio rpath") + panicOnErr(err) + } +} + +func unveil() { + paths := make(map[string]string) + + paths["/usr/share/dict"] = "r" + paths["/usr/local/share/dict"] = "r" + + // Unveil user defined dictionaries. + if len(os.Args) >= 3 { + for _, dict := range os.Args[2:] { + paths[dict] = "r" + } + } + // This will not return error if the file doesn't exist. + err := lynx.UnveilPaths(paths) + panicOnErr(err) + + // Block further unveil calls. + err = lynx.UnveilBlock() + panicOnErr(err) +} + +func panicOnErr(err error) { + if err != nil { + panic(err) + } +} -- cgit 1.4.1-2-gfad0