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

Last change on this file since 309 was 200, checked in by contact, 5 years ago

config: use shlex

This simplifies parsing and allows quoting words.

Closes: https://todo.sr.ht/~emersion/soju/43

File size: 2.1 KB
Line 
1package config
2
3import (
4 "bufio"
5 "fmt"
6 "io"
7 "os"
8
9 "github.com/google/shlex"
10)
11
12type TLS struct {
13 CertPath, KeyPath string
14}
15
16type Server struct {
17 Addr string
18 Hostname string
19 TLS *TLS
20 SQLDriver string
21 SQLSource string
22 LogPath string
23}
24
25func Defaults() *Server {
26 hostname, err := os.Hostname()
27 if err != nil {
28 hostname = "localhost"
29 }
30 return &Server{
31 Addr: ":6667",
32 Hostname: hostname,
33 SQLDriver: "sqlite3",
34 SQLSource: "soju.db",
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 scanner := bufio.NewScanner(r)
50
51 var directives []directive
52 for scanner.Scan() {
53 words, err := shlex.Split(scanner.Text())
54 if err != nil {
55 return nil, fmt.Errorf("failed to parse config file: %v", err)
56 } else if len(words) == 0 {
57 continue
58 }
59
60 name, params := words[0], words[1:]
61 directives = append(directives, directive{name, params})
62 }
63 if err := scanner.Err(); err != nil {
64 return nil, fmt.Errorf("failed to read config file: %v", err)
65 }
66
67 srv := Defaults()
68 for _, d := range directives {
69 switch d.Name {
70 case "listen":
71 if err := d.parseParams(&srv.Addr); err != nil {
72 return nil, err
73 }
74 case "hostname":
75 if err := d.parseParams(&srv.Hostname); err != nil {
76 return nil, err
77 }
78 case "tls":
79 tls := &TLS{}
80 if err := d.parseParams(&tls.CertPath, &tls.KeyPath); err != nil {
81 return nil, err
82 }
83 srv.TLS = tls
84 case "sql":
85 if err := d.parseParams(&srv.SQLDriver, &srv.SQLSource); err != nil {
86 return nil, err
87 }
88 case "log":
89 if err := d.parseParams(&srv.LogPath); err != nil {
90 return nil, err
91 }
92 default:
93 return nil, fmt.Errorf("unknown directive %q", d.Name)
94 }
95 }
96
97 return srv, nil
98}
99
100type directive struct {
101 Name string
102 Params []string
103}
104
105func (d *directive) parseParams(out ...*string) error {
106 if len(d.Params) != len(out) {
107 return fmt.Errorf("directive %q has wrong number of parameters: expected %v, got %v", d.Name, len(out), len(d.Params))
108 }
109 for i := range out {
110 *out[i] = d.Params[i]
111 }
112 return nil
113}
Note: See TracBrowser for help on using the repository browser.