* Added a sorry excuse for a configuration file parser.
authorUrban Wallasch <urban.wallasch@freenet.de>
Sat, 6 Apr 2019 22:04:02 +0000 (00:04 +0200)
committerUrban Wallasch <urban.wallasch@freenet.de>
Sat, 6 Apr 2019 22:04:02 +0000 (00:04 +0200)
.gitignore
README.md
config.go
gogopherd.cfg.example [new file with mode: 0644]
gogopherd.go
util.go

index 825745fc059af70ea8f7169757cc80fddcbe818d..afeadb185bcd7625e18bbc03657978d1b9b10e20 100644 (file)
@@ -1,2 +1,3 @@
 gogopherd
+gogopherd.cfg
 version.go
index f0c00c314aa1eaf0b3a8b026e97483863cf93c36..5795a6a97cb86a1cf16cd7d11e90fdbae2a09b54 100644 (file)
--- a/README.md
+++ b/README.md
@@ -18,8 +18,8 @@ _(Source: Wikipedia)_
 
 ## Motivation
 
-For the fun of it. Also, given the golang.org mascot, what could be
-more appropriate?
+For the fun of it. Also, considering the golang.org mascot, what
+could be more appropriate than writing gopher software in Go?
 
 
 ## Installation
@@ -35,37 +35,44 @@ The `gogopherd` executable recognizes the following command line
 options:
 
 ```
-  -M string
-        index greeter message
+  -I string
+      directory index page (default "index.goph")
+
+  -c string
+      configuration file (default "gogopherd.cfg")
 
   -d
-        allow access to dotfiles
+      allow access to dotfiles
 
   -f string
-        fully qualified domain name (default "localhost")
+      fully qualified domain name (default "localhost")
 
   -h
-        show this help page
+      show this help page
 
   -i string
-        interface to bind to (default "localhost")
+      interface to bind to (default "localhost")
 
   -l
-        allow directory listings
+      allow directory listings
 
   -p string
-        TCP port to listen on (default "7070")
+      TCP port to listen on (default "7070")
 
   -r string
-        document root directory (default ".")
+      document root directory (default ".")
 
   -s
-        follow symbolic links
+      follow symbolic links
 
   -v
-        produce verbose output
+      produce verbose output
 ```
 
+An example configuration file, `gogopherd.cfg`, is included. Any options
+provided on the command line will override the respective settings as
+read from the configuration file.
+
 
 ## Release History
 
index 29286582baa8d2ef779b61b399e597b337a1acc6..6e4817adf135a1da1f375d72a7d51772a8d8402c 100644 (file)
--- a/config.go
+++ b/config.go
@@ -11,6 +11,7 @@ package main
 import (
        "flag"
        "fmt"
+       "io/ioutil"
        "os"
        "path/filepath"
        "strings"
@@ -38,8 +39,51 @@ var cfg = struct {
        verbose: false,
 }
 
+func parseConfigFile(filename string) error {
+       tracer.Print("reading config from " + filename)
+       file, err := ioutil.ReadFile(filename)
+       if err != nil {
+               logger.Print("ReadFile: ", err.Error())
+               return err
+       }
+       lines := strings.Split(string(file), "\n")
+       for _, line := range lines {
+               line = strings.TrimSpace(string(line))
+               if len(line) == 0 || line[:1] == "#" || line[:1] == ";" {
+                       continue
+               }
+               assign := strings.Split(line, "=")
+               name := strings.ToLower(strings.TrimSpace(assign[0]))
+               val := strings.Trim(strings.TrimSpace(assign[1]), "\"")
+               tracer.Print(name + "=" + val)
+               switch name {
+               case "iface":
+                       cfg.iface = val
+               case "port":
+                       cfg.port = val
+               case "fqdn":
+                       cfg.fqdn = val
+               case "docroot":
+                       cfg.docRoot = val
+               case "diridx":
+                       cfg.dirIdx = val
+               case "fsymln":
+                       cfg.fsymln = strToBool(val)
+               case "showdot":
+                       cfg.showdot = strToBool(val)
+               case "noidx":
+                       cfg.noidx = strToBool(val)
+               default:
+                       logger.Print("ignoring unknown config item: " + name)
+               }
+       }
+       return nil
+}
+
 func initialize() {
        help := false
+       cfgfile := "gogopherd.cfg"
+       flag.StringVar(&cfgfile, "c", cfgfile, "configuration file")
        flag.StringVar(&cfg.iface, "i", cfg.iface, "interface to bind to")
        flag.StringVar(&cfg.port, "p", cfg.port, "TCP port to listen on")
        flag.StringVar(&cfg.fqdn, "f", cfg.fqdn, "fully qualified domain name")
@@ -62,8 +106,11 @@ func initialize() {
                flag.Usage()
                os.Exit(1)
        }
-
        initUtil(cfg.verbose)
+       if len(cfgfile) > 0 {
+               parseConfigFile(cfgfile)
+               flag.Parse()
+       }
 
        var err error
        cfg.docRoot, err = canonicalizePath(cfg.docRoot)
diff --git a/gogopherd.cfg.example b/gogopherd.cfg.example
new file mode 100644 (file)
index 0000000..d9a6464
--- /dev/null
@@ -0,0 +1,23 @@
+# Example configuration for gogopherd.
+# Command line options will override values set here.
+
+# Network interface to bind to, empty means all.
+iface = ""
+# TCP port to listen on.
+port = 7070
+# Fully qualified domain name associated with server.
+fqdn = "localhost"
+
+# Root directory of document hierarchy.
+docroot = "."
+# Name of directory index files.
+diridx = "index.goph"
+
+# If true, follow symbolic links.
+fsymln = true
+# Show dot files.
+showdot = false
+# Do not generate directory listings when no index file is present.
+noidx = false
+
+# EOF
index bc31d17013fd7802666e78e0ccf78a8318cdc871..29669f545c669e066d93bd2ce88df118ab784d88 100644 (file)
@@ -77,7 +77,7 @@ func createIndex(dirname string, selector string) (string, error) {
                                }
                        }
                } else {
-                       tracer.Print("unhandled file mode: " + fi.Name() + " (" + fmode.String() + ")")
+                       logger.Print("unhandled file mode: " + fi.Name() + " (" + fmode.String() + ")")
                }
        }
        return list, error(nil)
@@ -208,7 +208,7 @@ func serveTCP(sock net.Listener) {
        for {
                conn, err := sock.Accept()
                checkFatal(err, "Accept")
-               tracer.Print("TCP connect from ", conn.RemoteAddr())
+               logger.Print("TCP connect from ", conn.RemoteAddr())
                go handleRequest(conn)
        }
 }
@@ -219,7 +219,7 @@ func main() {
        tsock, err := net.Listen("tcp", bindaddr)
        checkFatal(err, "net.Listen tcp "+bindaddr)
        defer tsock.Close()
-       tracer.Print("listening on TCP ", bindaddr)
+       logger.Print("listening on TCP ", bindaddr)
        go serveTCP(tsock)
        // send ready signal
        fmt.Println("")
diff --git a/util.go b/util.go
index 29d453bdc8ec2eabcd73ad708cbffe1564465263..fef860a286c92a647fc595e896a37c4650631e0e 100644 (file)
--- a/util.go
+++ b/util.go
@@ -125,4 +125,12 @@ func humanDate(t time.Time) string {
        return t.Format("2006-01-02 15:04:05 -07:00")
 }
 
+func strToBool(s string) bool {
+       switch strings.ToLower(s) {
+       case "yes", "1", "on", "true", "aye", "yup":
+               return true
+       }
+       return false
+}
+
 /* EOF */