gogopherd
+gogopherd.cfg
version.go
## 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
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
import (
"flag"
"fmt"
+ "io/ioutil"
"os"
"path/filepath"
"strings"
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")
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)
--- /dev/null
+# 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
}
}
} else {
- tracer.Print("unhandled file mode: " + fi.Name() + " (" + fmode.String() + ")")
+ logger.Print("unhandled file mode: " + fi.Name() + " (" + fmode.String() + ")")
}
}
return list, error(nil)
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)
}
}
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("")
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 */