* Added option to send logging output to file.
authorUrban Wallasch <urban.wallasch@freenet.de>
Wed, 10 Apr 2019 11:15:50 +0000 (13:15 +0200)
committerUrban Wallasch <urban.wallasch@freenet.de>
Wed, 10 Apr 2019 11:15:50 +0000 (13:15 +0200)
* Moved logger to separate source file.

README.md
config.go
gogopherd.cfg.example
logger.go [new file with mode: 0644]
util.go

index 7abc92992324d9273b86f91d1b891c1e47387255..bef1629624b62a01e33ffe49c9500ed8ab61b785 100644 (file)
--- a/README.md
+++ b/README.md
@@ -45,7 +45,7 @@ options:
       directory index page (default "index.goph")
 
   -c string
-      configuration file (default "gogopherd.cfg")
+      configuration file
 
   -d
       allow access to dotfiles
@@ -74,6 +74,9 @@ options:
   -t int
       connection read/write timeout in seconds (default 60)
 
+  -L string
+      write log to file; empty for stderr
+
   -v
       produce verbose output
 ```
index 969dfaf4d3676e6d1cb99c87e534128019ce43a6..b0ee4bc88b32488baafe3ffefc68af72d9f7bc70 100644 (file)
--- a/config.go
+++ b/config.go
@@ -12,6 +12,7 @@ import (
        "flag"
        "fmt"
        "io/ioutil"
+       "log"
        "os"
        "path"
        "path/filepath"
@@ -31,6 +32,7 @@ var cfg = struct {
        showdot bool
        indexes bool
        timeout int
+       logfile string
        verbose bool
 }{
        iface:   "localhost",
@@ -44,16 +46,16 @@ var cfg = struct {
        showdot: false,
        indexes: false,
        timeout: 60,
+       logfile: "",
        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
        }
+       tracer.Print("reading config from ", filename)
        lines := strings.Split(string(file), "\n")
        for _, line := range lines {
                line = strings.TrimSpace(string(line))
@@ -87,20 +89,23 @@ func parseConfigFile(filename string) error {
                        cfg.indexes = strToBool(val)
                case "timeout":
                        cfg.timeout, _ = strconv.Atoi(val)
+               case "logfile":
+                       cfg.logfile = val
                case "verbose":
                        cfg.verbose = strToBool(val)
                default:
-                       logger.Print("ignoring unknown config item: ", name)
+                       logger.Print("ignoring unknown config file option: ", name)
                }
        }
        return nil
 }
 
 func initialize() {
+       var err error
        help := false
-       cfgfile := "gogopherd.cfg"
+       cfgfile := ""
        flag.StringVar(&cfgfile, "c", cfgfile, "configuration file")
-       flag.StringVar(&cfg.iface, "i", cfg.iface, "interface to bind to")
+       flag.StringVar(&cfg.iface, "i", cfg.iface, "interface to bind to; empty for any")
        flag.StringVar(&cfg.port, "p", cfg.port, "TCP port to listen on")
        flag.StringVar(&cfg.fqdn, "f", cfg.fqdn, "fully qualified domain name")
        flag.StringVar(&cfg.docroot, "r", cfg.docroot, "document root directory")
@@ -112,26 +117,27 @@ func initialize() {
        flag.BoolVar(&cfg.showdot, "d", cfg.showdot, "allow access to dotfiles")
        flag.BoolVar(&cfg.indexes, "l", cfg.indexes, "allow generated directory indexes")
        flag.IntVar(&cfg.timeout, "t", cfg.timeout, "connection read/write timeout in seconds")
+       flag.StringVar(&cfg.logfile, "L", cfg.logfile, "write log to file; empty for stderr")
        flag.BoolVar(&cfg.verbose, "v", cfg.verbose, "produce verbose output")
        flag.Parse()
        if help {
-               fmt.Println("Version ", version)
+               fmt.Println("gogopherd version ", version)
                flag.Usage()
                os.Exit(1)
        }
        if 0 != len(flag.Args()) {
-               fmt.Println("Version ", version)
-               fmt.Println("unrecognized options: ", flag.Args())
+               log.Println("unrecognized arguments: ", flag.Args())
                flag.Usage()
                os.Exit(1)
        }
-       initUtil(cfg.verbose)
+       initLogger(cfg.verbose, cfg.logfile)
        if len(cfgfile) > 0 {
-               parseConfigFile(cfgfile)
+               err = parseConfigFile(cfgfile)
+               checkFatal(err, "parseConfigFile")
                flag.Parse()
+               initLogger(cfg.verbose, cfg.logfile)
        }
 
-       var err error
        cfg.docroot, err = canonicalizePath(cfg.docroot)
        checkFatal(err, "canonicalizePath "+cfg.docroot)
        if filepath.IsAbs(cfg.header) {
@@ -145,7 +151,7 @@ func initialize() {
                cfg.idxpage = ""
        }
 
-       tracer.Print("final config after evaluating command line:")
+       tracer.Print("final config:")
        tracer.Print("fqdn:    ", cfg.fqdn)
        tracer.Print("iface:   ", cfg.iface)
        tracer.Print("port:    ", cfg.port)
index c3d00a4598ebf6f3a1d51646b1cb47c6e389eab5..64710ace2cec1fe6d8ea46eae043d768118b3081 100644 (file)
@@ -27,6 +27,9 @@ indexes = true
 # Connection read and write timeout in seconds
 timeout =  60
 
+# Log to file; leave empty for stderr
+logfile = ""
+
 # Produce verbose output
 verbose = false
 
diff --git a/logger.go b/logger.go
new file mode 100644 (file)
index 0000000..9b6dbca
--- /dev/null
+++ b/logger.go
@@ -0,0 +1,61 @@
+/*
+ * This file is part of the gogopherd project.
+ *
+ * Copyright 2019 Urban Wallasch <irrwahn35@freenet.de>
+ * See LICENSE file for more details.
+ *
+ */
+
+package main
+
+import (
+       "io/ioutil"
+       "log"
+       "os"
+       "path/filepath"
+       "runtime"
+)
+
+var (
+       logger *log.Logger
+       loggex *log.Logger
+       tracer *log.Logger
+       tracex *log.Logger
+)
+
+func initLogger(verbose bool, logfilename string) {
+       if len(logfilename) > 0 {
+               logfile, err := os.OpenFile(logfilename, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
+               if err != nil {
+                       log.Fatalln("Failed to open log file", logfilename, ":", err)
+               }
+               os.Stderr.Close()
+               os.Stderr = logfile
+       }
+       logger = log.New(os.Stderr, "", log.Ldate|log.Ltime|log.Lshortfile)
+       loggex = log.New(os.Stderr, "", log.Ldate|log.Ltime)
+       if verbose {
+               tracer = log.New(os.Stderr, "", log.Ldate|log.Ltime|log.Lshortfile)
+               tracex = log.New(os.Stderr, "", log.Ldate|log.Ltime)
+       } else {
+               tracer = log.New(ioutil.Discard, "", 0)
+               tracex = log.New(ioutil.Discard, "", 0)
+       }
+}
+
+func checkFatal(err error, msg string) {
+       if err != nil {
+               _, file, line, _ := runtime.Caller(1)
+               loggex.Fatalf("%s:%d: %s %v\n", filepath.Base(file), line, msg, err)
+       }
+}
+
+func check(err error, msg string) error {
+       if err != nil && cfg.verbose {
+               _, file, line, _ := runtime.Caller(1)
+               tracex.Printf("%s:%d: %s %v\n", filepath.Base(file), line, msg, err)
+       }
+       return err
+}
+
+/* EOF */
diff --git a/util.go b/util.go
index b31686fc459024276170b6b7e6d59593382969bd..056e1124ec09011bc36c84ea51deb21d8ca14ab1 100644 (file)
--- a/util.go
+++ b/util.go
@@ -12,51 +12,13 @@ import (
        "errors"
        "fmt"
        "io"
-       "io/ioutil"
-       "log"
        "net/http"
        "os"
        "path/filepath"
-       "runtime"
        "strings"
        "time"
 )
 
-var (
-       logger *log.Logger
-       loggex *log.Logger
-       tracer *log.Logger
-       tracex *log.Logger
-)
-
-func initUtil(verbose bool) {
-       logger = log.New(os.Stderr, "", log.Ldate|log.Ltime|log.Lshortfile)
-       loggex = log.New(os.Stderr, "", log.Ldate|log.Ltime)
-       if verbose {
-               tracer = log.New(os.Stderr, "", log.Ldate|log.Ltime|log.Lshortfile)
-               tracex = log.New(os.Stderr, "", log.Ldate|log.Ltime)
-       } else {
-               tracer = log.New(ioutil.Discard, "", 0)
-               tracex = log.New(ioutil.Discard, "", 0)
-       }
-}
-
-func checkFatal(err error, msg string) {
-       if err != nil {
-               _, file, line, _ := runtime.Caller(1)
-               loggex.Printf("%s:%d: %s %v\n", filepath.Base(file), line, msg, err)
-               os.Exit(1)
-       }
-}
-
-func check(err error, msg string) error {
-       if err != nil && cfg.verbose {
-               _, file, line, _ := runtime.Caller(1)
-               tracex.Printf("%s:%d: %s %v\n", filepath.Base(file), line, msg, err)
-       }
-       return err
-}
-
 func canonicalizePath(path string) (string, error) {
        abs, err := filepath.Abs(path)
        if check(err, "Abs "+path) != nil {