diff options
Diffstat (limited to 'cmd')
| -rw-r--r-- | cmd/tunneld/main.go | 106 |
1 files changed, 75 insertions, 31 deletions
diff --git a/cmd/tunneld/main.go b/cmd/tunneld/main.go index a0c0e03..908fcc3 100644 --- a/cmd/tunneld/main.go +++ b/cmd/tunneld/main.go @@ -13,6 +13,7 @@ import ( "os/signal" "os/user" "path" + "regexp" "strconv" "strings" "syscall" @@ -28,6 +29,10 @@ var ( socketFlag = flag.String("S", "", "path to control socket") ) +const trimSize = 32 + +var wordsRe = regexp.MustCompile("[[:^space:]]+") + func initLog() { var logFlags int @@ -85,56 +90,81 @@ func getSocketPath() string { return s } -func openConfig() (*os.File, error) { - var c string +type parser struct { + s *server.Server + m map[string]bool + f []string +} - if *configFlag != "" { - c = *configFlag - } else { - c = config.GetConfigPath() - } +func newParser(s *server.Server) *parser { + return &parser{s: s, m: map[string]bool{}} +} - if c == "" { - return nil, nil +func (p *parser) parse(file string, skip bool) error { + if p.m[file] { + log.Printf("skip reading '%s' twice", file) + return nil } - fp, err := os.Open(c) - if err != nil { - if *configFlag == "" && errors.Is(err, syscall.ENOENT) { - return nil, nil - } + p.m[file] = true + p.f = append(p.f, file) - return nil, err - } + defer func() { + p.f = p.f[:len(p.f)-1] + }() - return fp, nil -} + log.Println("read config", file) -func readConfig(s *server.Server) error { - fp, err := openConfig() - if fp == nil || err != nil { + fp, err := os.Open(file) + if err != nil { + if skip && errors.Is(err, syscall.ENOENT) { + return nil + } return err } defer fp.Close() + return p.read(fp) +} + +func (p *parser) read(fp *os.File) error { scanner := bufio.NewScanner(fp) - scanner.Split(bufio.ScanLines) for nline := 1; scanner.Scan(); nline++ { - args := strings.SplitN(scanner.Text(), "#", 2) - cmd := strings.TrimSpace(args[0]) + s := strings.SplitN(scanner.Text(), "#", 2) + t := strings.TrimSpace(s[0]) + args := wordsRe.FindAllString(s[0], -1) - if cmd == "" { - continue + if err := p.apply(args); err != nil { + return fmt.Errorf("%s:%d: %s: %w", fp.Name(), nline, t, err) } + } - if err := s.Command(cmd); err != nil { - return fmt.Errorf("%s:%d: %s: %w", fp.Name(), nline, cmd, err) + return nil +} + +func (p *parser) apply(args []string) error { + if len(args) == 0 { + return nil + } + + if args[0] == "include" { + if len(args) < 2 { + return errors.New("argument expected") } + + file := args[1] + + if !path.IsAbs(file) { + now := p.f[len(p.f)-1] + file = path.Join(path.Dir(now), file) + } + + return p.parse(file, false) } - return nil + return p.s.Command(args) } func updateSocketGroup(s *server.Server, group string) error { @@ -173,7 +203,7 @@ func updateSocketGroup(s *server.Server, group string) error { } func runCommand(s *server.Server, name string) error { - cmd := s.Env().Get(name) + cmd := s.Env().Value(name) if cmd == "" { return nil } @@ -209,10 +239,24 @@ func runCommand(s *server.Server, name string) error { } func configure(s *server.Server) error { - if err := readConfig(s); err != nil { + var file string + var skip bool + + if *configFlag != "" { + file = *configFlag + } else { + file = config.GetConfigPath() + skip = true + } + + if err := newParser(s).parse(file, skip); err != nil { return err } + return postconfigure(s) +} + +func postconfigure(s *server.Server) error { if group, ok := s.Env().Find("server.socket.group"); ok { if err := updateSocketGroup(s, group); err != nil { return err |
