Files
elmprodvpn/selective-vpn-api/app/cli/routes_update.go

66 lines
1.3 KiB
Go

package cli
import (
"flag"
"fmt"
"io"
"os"
"strings"
"syscall"
)
type RoutesUpdateDeps struct {
LockFile string
Update func(iface string) (ok bool, message string)
Stdout io.Writer
Stderr io.Writer
}
func RunRoutesUpdate(args []string, deps RoutesUpdateDeps) int {
if deps.Update == nil || deps.LockFile == "" {
return 1
}
stdout := deps.Stdout
if stdout == nil {
stdout = os.Stdout
}
stderr := deps.Stderr
if stderr == nil {
stderr = os.Stderr
}
fs := flag.NewFlagSet("routes-update", flag.ContinueOnError)
fs.SetOutput(stderr)
iface := fs.String("iface", "", "VPN interface (empty/auto = detect active)")
if err := fs.Parse(args); err != nil {
return 2
}
lock, err := os.OpenFile(deps.LockFile, os.O_CREATE|os.O_RDWR, 0o644)
if err != nil {
fmt.Fprintf(stderr, "lock open error: %v\n", err)
return 1
}
defer lock.Close()
if err := syscall.Flock(int(lock.Fd()), syscall.LOCK_EX|syscall.LOCK_NB); err != nil {
fmt.Fprintln(stdout, "routes update already running")
return 0
}
defer func() {
_ = syscall.Flock(int(lock.Fd()), syscall.LOCK_UN)
}()
ok, message := deps.Update(*iface)
if ok {
fmt.Fprintln(stdout, strings.TrimSpace(message))
return 0
}
msg := strings.TrimSpace(message)
if msg == "" {
msg = "routes update failed"
}
fmt.Fprintln(stderr, msg)
return 1
}