summaryrefslogtreecommitdiff
path: root/cmd/tunneld
diff options
context:
space:
mode:
authorMikhail Osipov <mike.osipov@gmail.com>2020-09-10 00:18:05 +0300
committerMikhail Osipov <mike.osipov@gmail.com>2020-09-10 00:18:05 +0300
commit92fdd0e34e1fddf3cc85c3e0691d4fd1196bc382 (patch)
tree91ad84809c7d46e06196bd931cbeda34b648e869 /cmd/tunneld
parentcc5f5c9dbd8076a3a119c2b0e214e4d9c4f9bb1d (diff)
expandable variable syntax
Diffstat (limited to 'cmd/tunneld')
-rw-r--r--cmd/tunneld/main.go106
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