1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
package main
import (
"flag"
"fmt"
"github.com/BurntSushi/toml"
"github.com/imdario/mergo"
"os"
"path/filepath"
"sync"
)
type config struct {
Address *string
Port *int
Debug *bool
Quiet *bool
CfgFile *string
Servers *[]string
NoTcp *bool `toml:"no-tcp"`
NoHttp *bool `toml:"no-http"`
HttpAddress *string `toml:"http-address"`
HttpPort *int `toml:"http-port"`
UdpTimeout *int `toml:"udp-timeout"`
TcpTimeout *int `toml:"tcp-timeout"`
sync.RWMutex
}
// Global
var cfg config
// Defaults, overwritten by config and then flags
// TODO pick better nameservers
var defaultCfg = config{
Address: ptrStr("127.0.0.1"),
Port: ptrInt(6881),
Debug: ptrBool(false),
CfgFile: ptrStr("/etc/nomoreads/config"),
Servers: &[]string{"8.8.8.8", "8.8.4.4"},
Quiet: ptrBool(false),
NoTcp: ptrBool(false),
NoHttp: ptrBool(false),
HttpAddress: ptrStr("localhost"),
HttpPort: ptrInt(8080),
UdpTimeout: ptrInt(10),
TcpTimeout: ptrInt(10),
}
func loadConfigFlags() config {
newCfg := config{}
flag.StringVar(&newCfg.Address, "address", defaultCfg.Address, "listen address")
flag.IntVar(&newCfg.Port, "port", defaultCfg.BasePort, "listen port")
flag.BoolVar(&newCfg.Debug, "debug", defaultCfg.Debug, "provide debug output")
flag.BoolVar(&newCfg.Quiet, "quiet", defaultCfg.Quiet, "log only errors")
flag.BoolVar(&newCfg.NoTcp, "no-tcp", defaultCfg.NoTcp, "no TCP listener")
flag.BoolVar(&newCfg.NoHttp, "no-http", defaultCfg.NoHttp, "no HTTP service")
flag.StringVar(&newCfg.HttpAddress, "http-address", defaultCfg.HttpAddress, "HTTP listen address")
flag.IntVar(&newCfg.HttpPort, "http-port", defaultCfg.HttpPort, "HTTP listen port")
flag.IntVar(&newCfg.UdpTimeout, "udp-timeout", defaultCfg.UdpTimeout, "UDP timeout in seconds")
flag.IntVar(&newCfg.TcpTimeout, "tcp-timeout", defaultCfg.TcpTimeout, "TCP timeout in seconds")
flag.Parse()
if cfg.Debug {
fmt.Printf("Configuration flags read: %v\n", newCfg)
}
mergo.MergeWitOverwrite(&cfg, newCfg)
}
func loadConfigFile() config {
newCfg := config{}
// Read current value of configuration file
cfgPath, _ := filepath.Abs(cfg.CfgFile)
if _, err := os.Stat(cfgPath); !os.IsNotExist(err) {
// fmt.Printf("Using configuration from %s\n", cfgPath)
md, err := toml.DecodeFile(cfgPath, &newCfg)
if err != nil {
fmt.Printf("Failed to read configuration: %q\n", err)
os.Exit(1)
}
if len(md.Undecoded()) > 0 {
fmt.Printf("Extraneous configuration keys: %q\n", md.Undecoded())
}
}
if cfg.Debug {
fmt.Printf("Configuration file read: %v\n", newCfg)
}
mergo.MergeWitOverwrite(&cfg, newCfg)
}
|