diff --git a/cmd/tailscale/cli/cert.go b/cmd/tailscale/cli/cert.go index c55cab86d..2011f73d3 100644 --- a/cmd/tailscale/cli/cert.go +++ b/cmd/tailscale/cli/cert.go @@ -29,7 +29,7 @@ ShortHelp: "get TLS certs", ShortUsage: "cert [flags] ", FlagSet: (func() *flag.FlagSet { - fs := flag.NewFlagSet("cert", flag.ExitOnError) + fs := newFlagSet("cert") fs.StringVar(&certArgs.certFile, "cert-file", "", "output cert file or \"-\" for stdout; defaults to DOMAIN.crt if --cert-file and --key-file are both unset") fs.StringVar(&certArgs.keyFile, "key-file", "", "output cert file or \"-\" for stdout; defaults to DOMAIN.key if --cert-file and --key-file are both unset") fs.BoolVar(&certArgs.serve, "serve-demo", false, "if true, serve on port :443 using the cert as a demo, instead of writing out the files to disk") diff --git a/cmd/tailscale/cli/cli.go b/cmd/tailscale/cli/cli.go index 6c1628ebc..37da5bc2d 100644 --- a/cmd/tailscale/cli/cli.go +++ b/cmd/tailscale/cli/cli.go @@ -77,6 +77,14 @@ func ActLikeCLI() bool { return false } +func newFlagSet(name string) *flag.FlagSet { + onError := flag.ExitOnError + if runtime.GOOS == "js" { + onError = flag.ContinueOnError + } + return flag.NewFlagSet(name, onError) +} + // Run runs the CLI. The args do not include the binary name. func Run(args []string) error { if len(args) == 1 && (args[0] == "-V" || args[0] == "--version") { @@ -90,7 +98,7 @@ func Run(args []string) error { }) }) - rootfs := flag.NewFlagSet("tailscale", flag.ExitOnError) + rootfs := newFlagSet("tailscale") rootfs.StringVar(&rootArgs.socket, "socket", paths.DefaultTailscaledSocket(), "path to tailscaled's unix socket") rootCmd := &ffcli.Command{ diff --git a/cmd/tailscale/cli/debug.go b/cmd/tailscale/cli/debug.go index 0c7d8edb5..7716863ef 100644 --- a/cmd/tailscale/cli/debug.go +++ b/cmd/tailscale/cli/debug.go @@ -27,7 +27,7 @@ Name: "debug", Exec: runDebug, FlagSet: (func() *flag.FlagSet { - fs := flag.NewFlagSet("debug", flag.ExitOnError) + fs := newFlagSet("debug") fs.BoolVar(&debugArgs.goroutines, "daemon-goroutines", false, "If true, dump the tailscaled daemon's goroutines") fs.BoolVar(&debugArgs.ipn, "ipn", false, "If true, subscribe to IPN notifications") fs.BoolVar(&debugArgs.prefs, "prefs", false, "If true, dump active prefs") diff --git a/cmd/tailscale/cli/file.go b/cmd/tailscale/cli/file.go index 9490ca5db..1476528a8 100644 --- a/cmd/tailscale/cli/file.go +++ b/cmd/tailscale/cli/file.go @@ -55,7 +55,7 @@ ShortHelp: "Copy file(s) to a host", Exec: runCp, FlagSet: (func() *flag.FlagSet { - fs := flag.NewFlagSet("cp", flag.ExitOnError) + fs := newFlagSet("cp") fs.StringVar(&cpArgs.name, "name", "", "alternate filename to use, especially useful when is \"-\" (stdin)") fs.BoolVar(&cpArgs.verbose, "verbose", false, "verbose output") fs.BoolVar(&cpArgs.targets, "targets", false, "list possible file cp targets") @@ -304,7 +304,7 @@ func runCpTargets(ctx context.Context, args []string) error { ShortHelp: "Move files out of the Tailscale file inbox", Exec: runFileGet, FlagSet: (func() *flag.FlagSet { - fs := flag.NewFlagSet("get", flag.ExitOnError) + fs := newFlagSet("get") fs.BoolVar(&getArgs.wait, "wait", false, "wait for a file to arrive if inbox is empty") fs.BoolVar(&getArgs.verbose, "verbose", false, "verbose output") return fs diff --git a/cmd/tailscale/cli/ip.go b/cmd/tailscale/cli/ip.go index 0c3910a6e..457d51916 100644 --- a/cmd/tailscale/cli/ip.go +++ b/cmd/tailscale/cli/ip.go @@ -23,7 +23,7 @@ LongHelp: "Shows the Tailscale IP address of the current machine without an argument. With an argument, it shows the IP of a named peer.", Exec: runIP, FlagSet: (func() *flag.FlagSet { - fs := flag.NewFlagSet("ip", flag.ExitOnError) + fs := newFlagSet("ip") fs.BoolVar(&ipArgs.want4, "4", false, "only print IPv4 address") fs.BoolVar(&ipArgs.want6, "6", false, "only print IPv6 address") return fs diff --git a/cmd/tailscale/cli/netcheck.go b/cmd/tailscale/cli/netcheck.go index 6b6e3b412..6beb4f405 100644 --- a/cmd/tailscale/cli/netcheck.go +++ b/cmd/tailscale/cli/netcheck.go @@ -33,7 +33,7 @@ ShortHelp: "Print an analysis of local network conditions", Exec: runNetcheck, FlagSet: (func() *flag.FlagSet { - fs := flag.NewFlagSet("netcheck", flag.ExitOnError) + fs := newFlagSet("netcheck") fs.StringVar(&netcheckArgs.format, "format", "", `output format; empty (for human-readable), "json" or "json-line"`) fs.DurationVar(&netcheckArgs.every, "every", 0, "if non-zero, do an incremental report with the given frequency") fs.BoolVar(&netcheckArgs.verbose, "verbose", false, "verbose logs") diff --git a/cmd/tailscale/cli/ping.go b/cmd/tailscale/cli/ping.go index 2182474a5..ef6382e1d 100644 --- a/cmd/tailscale/cli/ping.go +++ b/cmd/tailscale/cli/ping.go @@ -45,7 +45,7 @@ `), Exec: runPing, FlagSet: (func() *flag.FlagSet { - fs := flag.NewFlagSet("ping", flag.ExitOnError) + fs := newFlagSet("ping") fs.BoolVar(&pingArgs.verbose, "verbose", false, "verbose output") fs.BoolVar(&pingArgs.untilDirect, "until-direct", true, "stop once a direct path is established") fs.BoolVar(&pingArgs.tsmp, "tsmp", false, "do a TSMP-level ping (through IP + wireguard, but not involving host OS stack)") diff --git a/cmd/tailscale/cli/status.go b/cmd/tailscale/cli/status.go index 4abbb7815..99a3b6d6b 100644 --- a/cmd/tailscale/cli/status.go +++ b/cmd/tailscale/cli/status.go @@ -31,7 +31,7 @@ ShortHelp: "Show state of tailscaled and its connections", Exec: runStatus, FlagSet: (func() *flag.FlagSet { - fs := flag.NewFlagSet("status", flag.ExitOnError) + fs := newFlagSet("status") fs.BoolVar(&statusArgs.json, "json", false, "output in JSON format (WARNING: format subject to change)") fs.BoolVar(&statusArgs.web, "web", false, "run webserver with HTML showing status") fs.BoolVar(&statusArgs.active, "active", false, "filter output to only peers with active sessions (not applicable to web mode)") diff --git a/cmd/tailscale/cli/up.go b/cmd/tailscale/cli/up.go index 4a4baae81..3adaa3600 100644 --- a/cmd/tailscale/cli/up.go +++ b/cmd/tailscale/cli/up.go @@ -63,7 +63,7 @@ func effectiveGOOS() string { var upFlagSet = newUpFlagSet(effectiveGOOS(), &upArgs) func newUpFlagSet(goos string, upArgs *upArgsT) *flag.FlagSet { - upf := flag.NewFlagSet("up", flag.ExitOnError) + upf := newFlagSet("up") upf.BoolVar(&upArgs.qr, "qr", false, "show QR code for login URLs") upf.BoolVar(&upArgs.forceReauth, "force-reauth", false, "force reauthentication") diff --git a/cmd/tailscale/cli/version.go b/cmd/tailscale/cli/version.go index 904c11e11..fca0b3c9d 100644 --- a/cmd/tailscale/cli/version.go +++ b/cmd/tailscale/cli/version.go @@ -20,7 +20,7 @@ ShortUsage: "version [flags]", ShortHelp: "Print Tailscale version", FlagSet: (func() *flag.FlagSet { - fs := flag.NewFlagSet("version", flag.ExitOnError) + fs := newFlagSet("version") fs.BoolVar(&versionArgs.daemon, "daemon", false, "also print local node's daemon version") return fs })(), diff --git a/cmd/tailscale/cli/web.go b/cmd/tailscale/cli/web.go index 07a6565b6..003b5af39 100644 --- a/cmd/tailscale/cli/web.go +++ b/cmd/tailscale/cli/web.go @@ -76,7 +76,7 @@ type tmplData struct { `), FlagSet: (func() *flag.FlagSet { - webf := flag.NewFlagSet("web", flag.ExitOnError) + webf := newFlagSet("web") webf.StringVar(&webArgs.listen, "listen", "localhost:8088", "listen address; use port 0 for automatic") webf.BoolVar(&webArgs.cgi, "cgi", false, "run as CGI script") return webf