source: code/trunk/config/config.go@ 178

Last change on this file since 178 was 178, checked in by delthas, 5 years ago

Add support for bouncer logs

Add bouncer logs, in a network/channel/date.log format, in a similar
manner to ZNC log module. PRIVMSG, JOIN, PART, QUIT, MODE are logged.

Add a config directive for the logs file, including a way to disable
them entirely.

File size: 3.3 KB
RevLine 
[62]1package config
2
3import (
4 "bufio"
5 "fmt"
6 "io"
7 "os"
8 "strings"
9 "unicode"
10)
11
12type TLS struct {
13 CertPath, KeyPath string
14}
15
16type Server struct {
[77]17 Addr string
18 Hostname string
19 TLS *TLS
20 SQLDriver string
21 SQLSource string
[178]22 LogPath string
[62]23}
24
25func Defaults() *Server {
26 hostname, err := os.Hostname()
27 if err != nil {
28 hostname = "localhost"
29 }
30 return &Server{
[77]31 Addr: ":6667",
32 Hostname: hostname,
33 SQLDriver: "sqlite3",
[98]34 SQLSource: "soju.db",
[62]35 }
36}
37
38func Load(path string) (*Server, error) {
39 f, err := os.Open(path)
40 if err != nil {
41 return nil, err
42 }
43 defer f.Close()
44
45 return Parse(f)
46}
47
48func Parse(r io.Reader) (*Server, error) {
49 p := parser{br: bufio.NewReader(r)}
50 directives, err := p.file()
51 if err != nil {
52 return nil, fmt.Errorf("failed to parse config file: %v", err)
53 }
54
55 srv := Defaults()
56 for _, d := range directives {
57 switch d.Name {
58 case "listen":
59 if err := d.parseParams(&srv.Addr); err != nil {
60 return nil, err
61 }
62 case "hostname":
63 if err := d.parseParams(&srv.Hostname); err != nil {
64 return nil, err
65 }
66 case "tls":
67 tls := &TLS{}
68 if err := d.parseParams(&tls.CertPath, &tls.KeyPath); err != nil {
69 return nil, err
70 }
71 srv.TLS = tls
[77]72 case "sql":
73 if err := d.parseParams(&srv.SQLDriver, &srv.SQLSource); err != nil {
74 return nil, err
75 }
[178]76 case "log":
77 if err := d.parseParams(&srv.LogPath); err != nil {
78 return nil, err
79 }
[62]80 default:
81 return nil, fmt.Errorf("unknown directive %q", d.Name)
82 }
83 }
84
85 return srv, nil
86}
87
88type directive struct {
89 Name string
90 Params []string
91}
92
93func (d *directive) parseParams(out ...*string) error {
94 if len(d.Params) != len(out) {
95 return fmt.Errorf("directive %q has wrong number of parameters: expected %v, got %v", d.Name, len(out), len(d.Params))
96 }
97 for i := range out {
98 *out[i] = d.Params[i]
99 }
100 return nil
101}
102
103type parser struct {
104 br *bufio.Reader
105}
106
107func (p *parser) skipSpace() error {
108 for {
109 r, _, err := p.br.ReadRune()
110 if err == io.EOF {
111 break
112 } else if err != nil {
113 return err
114 }
115 if !unicode.IsSpace(r) || r == '\n' {
116 p.br.UnreadRune()
117 break
118 }
119 }
120 return nil
121}
122
123func (p *parser) atom() (string, error) {
124 var sb strings.Builder
125 for {
126 r, _, err := p.br.ReadRune()
127 if err == io.EOF && sb.Len() > 0 {
128 break
129 } else if err != nil {
130 return "", err
131 }
132 if unicode.IsSpace(r) {
133 p.br.UnreadRune()
134 if err := p.skipSpace(); err != nil {
135 return "", err
136 }
137 break
138 }
139 sb.WriteRune(r)
140 }
141 return sb.String(), nil
142}
143
144func (p *parser) directive() (*directive, error) {
145 name, err := p.atom()
146 if err == io.EOF {
147 return nil, io.EOF
148 } else if err != nil {
149 return nil, fmt.Errorf("failed to read directive name: %v", err)
150 }
151
152 var params []string
153 for {
154 r, _, err := p.br.ReadRune()
155 if err == io.EOF {
156 break
157 } else if err != nil {
158 return nil, err
159 }
160 if r == '\n' {
161 break
162 }
163 p.br.UnreadRune()
164
165 param, err := p.atom()
166 if err == io.EOF {
167 break
168 } else if err != nil {
169 return nil, fmt.Errorf("failed to read directive param: %v", err)
170 }
171 params = append(params, param)
172 }
173
174 return &directive{name, params}, nil
175}
176
177func (p *parser) file() ([]directive, error) {
178 var l []directive
179 for {
180 d, err := p.directive()
181 if err == io.EOF {
182 break
183 } else if err != nil {
184 return nil, err
185 }
186 l = append(l, *d)
187 }
188 return l, nil
189}
Note: See TracBrowser for help on using the repository browser.