...
1 package main
2
3 import (
4 "flag"
5 "fmt"
6 "log"
7 "os"
8 "os/signal"
9 "strings"
10 "sync"
11 "syscall"
12
13 "code.rocketnine.space/tslocum/ez"
14 "code.rocketnine.space/tslocum/sshtargate/portal"
15 "github.com/anmitsu/go-shlex"
16 )
17
18 const (
19 version = "0.0.0"
20
21 versionInfo = `sshtargate - Host SSH portals to applications - v` + version + `
22 https://code.rocketnine.space/tslocum/sshtargate
23 The MIT License (MIT)
24 Copyright (c) 2020 Trevor Slocum <trevor@rocketnine.space>
25 `
26 )
27
28 var (
29 printVersionInfo bool
30 configPath string
31
32 portals []*portal.Portal
33 portalsLock = new(sync.Mutex)
34
35 done = make(chan bool)
36 )
37
38 func main() {
39 flag.BoolVar(&printVersionInfo, "version", false, "print version information and exit")
40 flag.StringVar(&configPath, "config", "", "path to configuration file")
41 flag.Parse()
42
43 if printVersionInfo {
44 fmt.Print(versionInfo)
45 return
46 }
47
48 if configPath == "" {
49 var err error
50 configPath, err = ez.DefaultConfigPath("sshtargate")
51 if err != nil {
52 log.Fatal(err)
53 }
54 }
55
56
57
58
59 sigc := make(chan os.Signal, 1)
60 signal.Notify(sigc,
61 syscall.SIGINT,
62 syscall.SIGTERM)
63 go func() {
64 <-sigc
65
66 done <- true
67 }()
68
69 log.Println("Initializing sshtargate...")
70
71 err := ez.Deserialize(config, configPath)
72 if err != nil {
73 log.Fatalf("failed to read configuration file: %s", err)
74 }
75
76 if len(config.Portals) == 0 {
77 log.Println("Warning: No portals are defined")
78 }
79
80 for pname, pcfg := range config.Portals {
81 cs, err := shlex.Split(pcfg.Command, true)
82 if err != nil {
83 log.Fatalf("failed to split command %s", pcfg.Command)
84 }
85
86 pname, pcfg := pname, pcfg
87 go func() {
88 wg := new(sync.WaitGroup)
89
90 for _, address := range pcfg.Host {
91 wg.Add(1)
92 address := address
93
94 go func() {
95 p, err := portal.New(pname, address, cs)
96 if err != nil {
97 log.Fatalf("failed to start portal %s on %s: %s", pname, address, err)
98 }
99
100 portalsLock.Lock()
101 portals = append(portals, p)
102 portalsLock.Unlock()
103
104 wg.Done()
105 }()
106 }
107
108 wg.Wait()
109 log.Printf("Opened portal %s on %s to %s", pname, strings.Join(pcfg.Host, ","), pcfg.Command)
110 }()
111 }
112
113 <-done
114
115 portalsLock.Lock()
116 for _, p := range portals {
117 p.Shutdown()
118 }
119 portalsLock.Unlock()
120 }
121
View as plain text