diff --git a/cmd/tailscale/cli/bugreport.go b/cmd/tailscale/cli/bugreport.go index f22193131..5595b66b2 100644 --- a/cmd/tailscale/cli/bugreport.go +++ b/cmd/tailscale/cli/bugreport.go @@ -7,6 +7,7 @@ import ( "context" "errors" + "fmt" "github.com/peterbourgon/ff/v3/ffcli" ) @@ -31,6 +32,6 @@ func runBugReport(ctx context.Context, args []string) error { if err != nil { return err } - outln(logMarker) + fmt.Println(logMarker) return nil } diff --git a/cmd/tailscale/cli/cert.go b/cmd/tailscale/cli/cert.go index e2a525bda..cb7a3a94f 100644 --- a/cmd/tailscale/cli/cert.go +++ b/cmd/tailscale/cli/cert.go @@ -27,7 +27,7 @@ ShortHelp: "get TLS certs", ShortUsage: "cert [flags] ", FlagSet: (func() *flag.FlagSet { - fs := newFlagSet("cert") + fs := flag.NewFlagSet("cert", flag.ExitOnError) 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") @@ -79,7 +79,7 @@ func runCert(ctx context.Context, args []string) error { domain := args[0] printf := func(format string, a ...any) { - printf(format, a...) + fmt.Printf(format, a...) } if certArgs.certFile == "-" || certArgs.keyFile == "-" { printf = log.Printf @@ -138,7 +138,7 @@ func runCert(ctx context.Context, args []string) error { func writeIfChanged(filename string, contents []byte, mode os.FileMode) (changed bool, err error) { if filename == "-" { - Stdout.Write(contents) + os.Stdout.Write(contents) return false, nil } if old, err := os.ReadFile(filename); err == nil && bytes.Equal(contents, old) { diff --git a/cmd/tailscale/cli/cli.go b/cmd/tailscale/cli/cli.go index fa76ba33e..cfc320ff3 100644 --- a/cmd/tailscale/cli/cli.go +++ b/cmd/tailscale/cli/cli.go @@ -33,22 +33,6 @@ "tailscale.com/version/distro" ) -var Stderr io.Writer = os.Stderr -var Stdout io.Writer = os.Stdout - -func printf(format string, a ...any) { - fmt.Fprintf(Stdout, format, a...) -} - -// outln is like fmt.Println in the common case, except when Stdout is -// changed (as in js/wasm). -// -// It's not named println because that looks like the Go built-in -// which goes to stderr and formats slightly differently. -func outln(a ...any) { - fmt.Fprintln(Stdout, a...) -} - // ActLikeCLI reports whether a GUI application should act like the // CLI based on os.Args, GOOS, the context the process is running in // (pty, parent PID), etc. @@ -95,16 +79,6 @@ func ActLikeCLI() bool { return false } -func newFlagSet(name string) *flag.FlagSet { - onError := flag.ExitOnError - if runtime.GOOS == "js" { - onError = flag.ContinueOnError - } - fs := flag.NewFlagSet(name, onError) - fs.SetOutput(Stderr) - return fs -} - // CleanUpArgs rewrites command line arguments for simplicity and backwards compatibility. // In particular, it rewrites --authkey to --auth-key. func CleanUpArgs(args []string) []string { @@ -138,11 +112,11 @@ func Run(args []string) (err error) { var warnOnce sync.Once tailscale.SetVersionMismatchHandler(func(clientVer, serverVer string) { warnOnce.Do(func() { - fmt.Fprintf(Stderr, "Warning: client version %q != tailscaled server version %q\n", clientVer, serverVer) + fmt.Fprintf(os.Stderr, "Warning: client version %q != tailscaled server version %q\n", clientVer, serverVer) }) }) - rootfs := newFlagSet("tailscale") + rootfs := flag.NewFlagSet("tailscale", flag.ExitOnError) rootfs.StringVar(&rootArgs.socket, "socket", paths.DefaultTailscaledSocket(), "path to tailscaled's unix socket") rootCmd := &ffcli.Command{ diff --git a/cmd/tailscale/cli/configure-host.go b/cmd/tailscale/cli/configure-host.go index b54fc83b8..14cb6824b 100644 --- a/cmd/tailscale/cli/configure-host.go +++ b/cmd/tailscale/cli/configure-host.go @@ -31,7 +31,7 @@ See: https://tailscale.com/kb/1152/synology-outbound/ `), FlagSet: (func() *flag.FlagSet { - fs := newFlagSet("configure-host") + fs := flag.NewFlagSet("configure-host", flag.ExitOnError) return fs })(), } diff --git a/cmd/tailscale/cli/debug.go b/cmd/tailscale/cli/debug.go index 9ff05e496..ec98b63c0 100644 --- a/cmd/tailscale/cli/debug.go +++ b/cmd/tailscale/cli/debug.go @@ -40,7 +40,7 @@ Exec: runDebug, LongHelp: `"tailscale debug" contains misc debug facilities; it is not a stable interface.`, FlagSet: (func() *flag.FlagSet { - fs := newFlagSet("debug") + fs := flag.NewFlagSet("debug", flag.ExitOnError) fs.StringVar(&debugArgs.file, "file", "", "get, delete:NAME, or NAME") fs.StringVar(&debugArgs.cpuFile, "cpu-profile", "", "if non-empty, grab a CPU profile for --profile-sec seconds and write it to this file; - for stdout") fs.StringVar(&debugArgs.memFile, "mem-profile", "", "if non-empty, grab a memory profile and write it to this file; - for stdout") @@ -63,7 +63,7 @@ Exec: runDaemonMetrics, ShortHelp: "print tailscaled's metrics", FlagSet: (func() *flag.FlagSet { - fs := newFlagSet("metrics") + fs := flag.NewFlagSet("metrics", flag.ExitOnError) fs.BoolVar(&metricsArgs.watch, "watch", false, "print JSON dump of delta values") return fs })(), @@ -103,7 +103,7 @@ Exec: runPrefs, ShortHelp: "print prefs", FlagSet: (func() *flag.FlagSet { - fs := newFlagSet("prefs") + fs := flag.NewFlagSet("prefs", flag.ExitOnError) fs.BoolVar(&prefsArgs.pretty, "pretty", false, "If true, pretty-print output") return fs })(), @@ -113,7 +113,7 @@ Exec: runWatchIPN, ShortHelp: "subscribe to IPN message bus", FlagSet: (func() *flag.FlagSet { - fs := newFlagSet("watch-ipn") + fs := flag.NewFlagSet("watch-ipn", flag.ExitOnError) fs.BoolVar(&watchIPNArgs.netmap, "netmap", true, "include netmap in messages") return fs })(), @@ -128,7 +128,7 @@ Exec: runTS2021, ShortHelp: "debug ts2021 protocol connectivity", FlagSet: (func() *flag.FlagSet { - fs := newFlagSet("ts2021") + fs := flag.NewFlagSet("ts2021", flag.ExitOnError) fs.StringVar(&ts2021Args.host, "host", "controlplane.tailscale.com", "hostname of control plane") fs.IntVar(&ts2021Args.version, "version", int(tailcfg.CurrentCapabilityVersion), "protocol version") return fs @@ -146,7 +146,7 @@ func writeProfile(dst string, v []byte) error { if dst == "-" { - _, err := Stdout.Write(v) + _, err := os.Stdout.Write(v) return err } return os.WriteFile(dst, v, 0600) @@ -198,7 +198,7 @@ func runDebug(ctx context.Context, args []string) error { if err != nil { fatalf("%v\n", err) } - e := json.NewEncoder(Stdout) + e := json.NewEncoder(os.Stdout) e.SetIndent("", "\t") e.Encode(wfs) return nil @@ -212,7 +212,7 @@ func runDebug(ctx context.Context, args []string) error { return err } log.Printf("Size: %v\n", size) - io.Copy(Stdout, rc) + io.Copy(os.Stdout, rc) return nil } if usedFlag { @@ -226,14 +226,14 @@ func runDebug(ctx context.Context, args []string) error { func runLocalCreds(ctx context.Context, args []string) error { port, token, err := safesocket.LocalTCPPortAndToken() if err == nil { - printf("curl -u:%s http://localhost:%d/localapi/v0/status\n", token, port) + fmt.Printf("curl -u:%s http://localhost:%d/localapi/v0/status\n", token, port) return nil } if runtime.GOOS == "windows" { - printf("curl http://localhost:%v/localapi/v0/status\n", safesocket.WindowsLocalPort) + fmt.Printf("curl http://localhost:%v/localapi/v0/status\n", safesocket.WindowsLocalPort) return nil } - printf("curl --unix-socket %s http://foo/localapi/v0/status\n", paths.DefaultTailscaledSocket()) + fmt.Printf("curl --unix-socket %s http://foo/localapi/v0/status\n", paths.DefaultTailscaledSocket()) return nil } @@ -247,10 +247,10 @@ func runPrefs(ctx context.Context, args []string) error { return err } if prefsArgs.pretty { - outln(prefs.Pretty()) + fmt.Println(prefs.Pretty()) } else { j, _ := json.MarshalIndent(prefs, "", "\t") - outln(string(j)) + fmt.Println(string(j)) } return nil } @@ -268,7 +268,7 @@ func runWatchIPN(ctx context.Context, args []string) error { n.NetMap = nil } j, _ := json.MarshalIndent(n, "", "\t") - printf("%s\n", j) + fmt.Printf("%s\n", j) }) bc.RequestEngineStatus() pump(ctx, bc, c) @@ -282,7 +282,7 @@ func runDERPMap(ctx context.Context, args []string) error { "failed to get local derp map, instead `curl %s/derpmap/default`: %w", ipn.DefaultControlURL, err, ) } - enc := json.NewEncoder(Stdout) + enc := json.NewEncoder(os.Stdout) enc.SetIndent("", "\t") enc.Encode(dm) return nil @@ -299,7 +299,7 @@ func localAPIAction(action string) func(context.Context, []string) error { func runEnv(ctx context.Context, args []string) error { for _, e := range os.Environ() { - outln(e) + fmt.Println(e) } return nil } @@ -338,7 +338,7 @@ func runDaemonGoroutines(ctx context.Context, args []string) error { if err != nil { return err } - Stdout.Write(goroutines) + os.Stdout.Write(goroutines) return nil } @@ -354,7 +354,7 @@ func runDaemonMetrics(ctx context.Context, args []string) error { return err } if !metricsArgs.watch { - Stdout.Write(out) + os.Stdout.Write(out) return nil } bs := bufio.NewScanner(bytes.NewReader(out)) @@ -391,9 +391,9 @@ type change struct { if len(changes) > 0 { format := fmt.Sprintf("%%-%ds %%+5d => %%v\n", maxNameLen) for _, c := range changes { - fmt.Fprintf(Stdout, format, c.name, c.to-c.from, c.to) + fmt.Fprintf(os.Stdout, format, c.name, c.to-c.from, c.to) } - io.WriteString(Stdout, "\n") + io.WriteString(os.Stdout, "\n") } time.Sleep(time.Second) } diff --git a/cmd/tailscale/cli/down.go b/cmd/tailscale/cli/down.go index 9a139f315..34ed3765c 100644 --- a/cmd/tailscale/cli/down.go +++ b/cmd/tailscale/cli/down.go @@ -8,6 +8,7 @@ "context" "flag" "fmt" + "os" "github.com/peterbourgon/ff/v3/ffcli" "tailscale.com/ipn" @@ -23,7 +24,7 @@ } func newDownFlagSet() *flag.FlagSet { - downf := newFlagSet("down") + downf := flag.NewFlagSet("down", flag.ExitOnError) registerAcceptRiskFlag(downf) return downf } @@ -44,7 +45,7 @@ func runDown(ctx context.Context, args []string) error { return fmt.Errorf("error fetching current status: %w", err) } if st.BackendState == "Stopped" { - fmt.Fprintf(Stderr, "Tailscale was already stopped.\n") + fmt.Fprintf(os.Stderr, "Tailscale was already stopped.\n") return nil } _, err = localClient.EditPrefs(ctx, &ipn.MaskedPrefs{ diff --git a/cmd/tailscale/cli/file.go b/cmd/tailscale/cli/file.go index 4b29ddbc7..4d7cf7d54 100644 --- a/cmd/tailscale/cli/file.go +++ b/cmd/tailscale/cli/file.go @@ -54,7 +54,7 @@ ShortHelp: "Copy file(s) to a host", Exec: runCp, FlagSet: (func() *flag.FlagSet { - fs := newFlagSet("cp") + fs := flag.NewFlagSet("cp", flag.ExitOnError) 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") @@ -100,7 +100,7 @@ func runCp(ctx context.Context, args []string) error { return fmt.Errorf("can't send to %s: %v", target, err) } if isOffline { - fmt.Fprintf(Stderr, "# warning: %s is offline\n", target) + fmt.Fprintf(os.Stderr, "# warning: %s is offline\n", target) } if len(files) > 1 { @@ -281,7 +281,7 @@ func runCpTargets(ctx context.Context, args []string) error { if detail != "" { detail = "\t" + detail } - printf("%s\t%s%s\n", n.Addresses[0].Addr(), n.ComputedName, detail) + fmt.Printf("%s\t%s%s\n", n.Addresses[0].Addr(), n.ComputedName, detail) } return nil } @@ -315,7 +315,7 @@ func (v *onConflict) Set(s string) error { ShortHelp: "Move files out of the Tailscale file inbox", Exec: runFileGet, FlagSet: (func() *flag.FlagSet { - fs := newFlagSet("get") + fs := flag.NewFlagSet("get", flag.ExitOnError) fs.BoolVar(&getArgs.wait, "wait", false, "wait for a file to arrive if inbox is empty") fs.BoolVar(&getArgs.loop, "loop", false, "run get in a loop, receiving files as they come in") fs.BoolVar(&getArgs.verbose, "verbose", false, "verbose output") @@ -415,7 +415,7 @@ func runFileGetOneBatch(ctx context.Context, dir string) []error { break } if getArgs.verbose { - printf("waiting for file...") + fmt.Printf("waiting for file...") } if err := waitForFile(ctx); err != nil { errs = append(errs, err) @@ -436,7 +436,7 @@ func runFileGetOneBatch(ctx context.Context, dir string) []error { continue } if getArgs.verbose { - printf("wrote %v as %v (%d bytes)\n", wf.Name, writtenFile, size) + fmt.Printf("wrote %v as %v (%d bytes)\n", wf.Name, writtenFile, size) } if err = localClient.DeleteWaitingFile(ctx, wf.Name); err != nil { errs = append(errs, fmt.Errorf("deleting %q from inbox: %v", wf.Name, err)) @@ -448,7 +448,7 @@ func runFileGetOneBatch(ctx context.Context, dir string) []error { // persistently stuck files are basically an error errs = append(errs, fmt.Errorf("moved %d/%d files", deleted, len(wfs))) } else if getArgs.verbose { - printf("moved %d/%d files\n", deleted, len(wfs)) + fmt.Printf("moved %d/%d files\n", deleted, len(wfs)) } return errs } @@ -471,7 +471,7 @@ func runFileGet(ctx context.Context, args []string) error { for { errs := runFileGetOneBatch(ctx, dir) for _, err := range errs { - outln(err) + fmt.Println(err) } if len(errs) > 0 { // It's possible whatever caused the error(s) (e.g. conflicting target file, @@ -493,7 +493,7 @@ func runFileGet(ctx context.Context, args []string) error { return nil } for _, err := range errs[:len(errs)-1] { - outln(err) + fmt.Println(err) } return errs[len(errs)-1] } diff --git a/cmd/tailscale/cli/ip.go b/cmd/tailscale/cli/ip.go index 53790aaa4..91ff44914 100644 --- a/cmd/tailscale/cli/ip.go +++ b/cmd/tailscale/cli/ip.go @@ -22,7 +22,7 @@ LongHelp: "Show Tailscale IP addresses for peer. Peer defaults to the current machine.", Exec: runIP, FlagSet: (func() *flag.FlagSet { - fs := newFlagSet("ip") + fs := flag.NewFlagSet("ip", flag.ExitOnError) fs.BoolVar(&ipArgs.want1, "1", false, "only print one IP address") fs.BoolVar(&ipArgs.want4, "4", false, "only print IPv4 address") fs.BoolVar(&ipArgs.want6, "6", false, "only print IPv6 address") @@ -85,7 +85,7 @@ func runIP(ctx context.Context, args []string) error { for _, ip := range ips { if ip.Is4() && v4 || ip.Is6() && v6 { match = true - outln(ip) + fmt.Println(ip) } } if !match { diff --git a/cmd/tailscale/cli/nc.go b/cmd/tailscale/cli/nc.go index 1f9edb185..b0a2490cd 100644 --- a/cmd/tailscale/cli/nc.go +++ b/cmd/tailscale/cli/nc.go @@ -29,7 +29,7 @@ func runNC(ctx context.Context, args []string) error { } description, ok := isRunningOrStarting(st) if !ok { - printf("%s\n", description) + fmt.Printf("%s\n", description) os.Exit(1) } diff --git a/cmd/tailscale/cli/netcheck.go b/cmd/tailscale/cli/netcheck.go index a835b9189..549f25c47 100644 --- a/cmd/tailscale/cli/netcheck.go +++ b/cmd/tailscale/cli/netcheck.go @@ -13,6 +13,7 @@ "io/ioutil" "log" "net/http" + "os" "sort" "strings" "time" @@ -32,7 +33,7 @@ ShortHelp: "Print an analysis of local network conditions", Exec: runNetcheck, FlagSet: (func() *flag.FlagSet { - fs := newFlagSet("netcheck") + fs := flag.NewFlagSet("netcheck", flag.ExitOnError) 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") @@ -59,7 +60,7 @@ func runNetcheck(ctx context.Context, args []string) error { } if strings.HasPrefix(netcheckArgs.format, "json") { - fmt.Fprintln(Stderr, "# Warning: this JSON format is not yet considered a stable interface") + fmt.Fprintln(os.Stderr, "# Warning: this JSON format is not yet considered a stable interface") } dm, err := localClient.CurrentDERPMap(ctx) @@ -111,38 +112,38 @@ func printReport(dm *tailcfg.DERPMap, report *netcheck.Report) error { } if j != nil { j = append(j, '\n') - Stdout.Write(j) + os.Stdout.Write(j) return nil } - printf("\nReport:\n") - printf("\t* UDP: %v\n", report.UDP) + fmt.Printf("\nReport:\n") + fmt.Printf("\t* UDP: %v\n", report.UDP) if report.GlobalV4 != "" { - printf("\t* IPv4: yes, %v\n", report.GlobalV4) + fmt.Printf("\t* IPv4: yes, %v\n", report.GlobalV4) } else { - printf("\t* IPv4: (no addr found)\n") + fmt.Printf("\t* IPv4: (no addr found)\n") } if report.GlobalV6 != "" { - printf("\t* IPv6: yes, %v\n", report.GlobalV6) + fmt.Printf("\t* IPv6: yes, %v\n", report.GlobalV6) } else if report.IPv6 { - printf("\t* IPv6: (no addr found)\n") + fmt.Printf("\t* IPv6: (no addr found)\n") } else if report.OSHasIPv6 { - printf("\t* IPv6: no, but OS has support\n") + fmt.Printf("\t* IPv6: no, but OS has support\n") } else { - printf("\t* IPv6: no, unavailable in OS\n") + fmt.Printf("\t* IPv6: no, unavailable in OS\n") } - printf("\t* MappingVariesByDestIP: %v\n", report.MappingVariesByDestIP) - printf("\t* HairPinning: %v\n", report.HairPinning) - printf("\t* PortMapping: %v\n", portMapping(report)) + fmt.Printf("\t* MappingVariesByDestIP: %v\n", report.MappingVariesByDestIP) + fmt.Printf("\t* HairPinning: %v\n", report.HairPinning) + fmt.Printf("\t* PortMapping: %v\n", portMapping(report)) // When DERP latency checking failed, // magicsock will try to pick the DERP server that // most of your other nodes are also using if len(report.RegionLatency) == 0 { - printf("\t* Nearest DERP: unknown (no response to latency probes)\n") + fmt.Printf("\t* Nearest DERP: unknown (no response to latency probes)\n") } else { - printf("\t* Nearest DERP: %v\n", dm.Regions[report.PreferredDERP].RegionName) - printf("\t* DERP latency:\n") + fmt.Printf("\t* Nearest DERP: %v\n", dm.Regions[report.PreferredDERP].RegionName) + fmt.Printf("\t* DERP latency:\n") var rids []int for rid := range dm.Regions { rids = append(rids, rid) @@ -169,7 +170,7 @@ func printReport(dm *tailcfg.DERPMap, report *netcheck.Report) error { if netcheckArgs.verbose { derpNum = fmt.Sprintf("derp%d, ", rid) } - printf("\t\t- %3s: %-7s (%s%s)\n", r.RegionCode, latency, derpNum, r.RegionName) + fmt.Printf("\t\t- %3s: %-7s (%s%s)\n", r.RegionCode, latency, derpNum, r.RegionName) } } return nil diff --git a/cmd/tailscale/cli/ping.go b/cmd/tailscale/cli/ping.go index de4970d89..60f949113 100644 --- a/cmd/tailscale/cli/ping.go +++ b/cmd/tailscale/cli/ping.go @@ -46,7 +46,7 @@ `), Exec: runPing, FlagSet: (func() *flag.FlagSet { - fs := newFlagSet("ping") + fs := flag.NewFlagSet("ping", flag.ExitOnError) 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 WireGuard, but not either host OS stack)") @@ -88,7 +88,7 @@ func runPing(ctx context.Context, args []string) error { } description, ok := isRunningOrStarting(st) if !ok { - printf("%s\n", description) + fmt.Printf("%s\n", description) os.Exit(1) } @@ -103,7 +103,7 @@ func runPing(ctx context.Context, args []string) error { return err } if self { - printf("%v is local Tailscale IP\n", ip) + fmt.Printf("%v is local Tailscale IP\n", ip) return nil } @@ -120,7 +120,7 @@ func runPing(ctx context.Context, args []string) error { cancel() if err != nil { if errors.Is(err, context.DeadlineExceeded) { - printf("ping %q timed out\n", ip) + fmt.Printf("ping %q timed out\n", ip) if n == pingArgs.num { if !anyPong { return errors.New("no reply") @@ -133,7 +133,7 @@ func runPing(ctx context.Context, args []string) error { } if pr.Err != "" { if pr.IsLocalIP { - outln(pr.Err) + fmt.Println(pr.Err) return nil } return errors.New(pr.Err) @@ -149,7 +149,7 @@ func runPing(ctx context.Context, args []string) error { via = string(pingType()) } if pingArgs.peerAPI { - printf("hit peerapi of %s (%s) at %s in %s\n", pr.NodeIP, pr.NodeName, pr.PeerAPIURL, latency) + fmt.Printf("hit peerapi of %s (%s) at %s in %s\n", pr.NodeIP, pr.NodeName, pr.PeerAPIURL, latency) return nil } anyPong = true @@ -157,7 +157,7 @@ func runPing(ctx context.Context, args []string) error { if pr.PeerAPIPort != 0 { extra = fmt.Sprintf(", %d", pr.PeerAPIPort) } - printf("pong from %s (%s%s) via %v in %v\n", pr.NodeName, pr.NodeIP, extra, via, latency) + fmt.Printf("pong from %s (%s%s) via %v in %v\n", pr.NodeName, pr.NodeIP, extra, via, latency) if pingArgs.tsmp || pingArgs.icmp { return nil } diff --git a/cmd/tailscale/cli/ssh_exec.go b/cmd/tailscale/cli/ssh_exec.go index bee4d3242..c2153dc36 100644 --- a/cmd/tailscale/cli/ssh_exec.go +++ b/cmd/tailscale/cli/ssh_exec.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build !js && !windows -// +build !js,!windows +//go:build !windows +// +build !windows package cli diff --git a/cmd/tailscale/cli/ssh_exec_js.go b/cmd/tailscale/cli/ssh_exec_js.go deleted file mode 100644 index 3dbbea6a2..000000000 --- a/cmd/tailscale/cli/ssh_exec_js.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) 2022 Tailscale Inc & AUTHORS All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cli - -import ( - "errors" -) - -func findSSH() (string, error) { - return "", errors.New("Not implemented") -} - -func execSSH(ssh string, argv []string) error { - return errors.New("Not implemented") -} diff --git a/cmd/tailscale/cli/status.go b/cmd/tailscale/cli/status.go index 830b2f000..5b65dbebc 100644 --- a/cmd/tailscale/cli/status.go +++ b/cmd/tailscale/cli/status.go @@ -46,7 +46,7 @@ `), Exec: runStatus, FlagSet: (func() *flag.FlagSet { - fs := newFlagSet("status") + fs := flag.NewFlagSet("status", flag.ExitOnError) 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)") @@ -92,7 +92,7 @@ func runStatus(ctx context.Context, args []string) error { if err != nil { return err } - printf("%s", j) + fmt.Printf("%s", j) return nil } if statusArgs.web { @@ -101,7 +101,7 @@ func runStatus(ctx context.Context, args []string) error { return err } statusURL := interfaces.HTTPOfListener(ln) - printf("Serving Tailscale status at %v ...\n", statusURL) + fmt.Printf("Serving Tailscale status at %v ...\n", statusURL) go func() { <-ctx.Done() ln.Close() @@ -131,16 +131,16 @@ func runStatus(ctx context.Context, args []string) error { // print health check information prior to checking LocalBackend state as // it may provide an explanation to the user if we choose to exit early if len(st.Health) > 0 { - printf("# Health check:\n") + fmt.Printf("# Health check:\n") for _, m := range st.Health { - printf("# - %s\n", m) + fmt.Printf("# - %s\n", m) } - outln() + fmt.Println() } description, ok := isRunningOrStarting(st) if !ok { - outln(description) + fmt.Println(description) os.Exit(1) } @@ -213,7 +213,7 @@ func runStatus(ctx context.Context, args []string) error { printPS(ps) } } - Stdout.Write(buf.Bytes()) + os.Stdout.Write(buf.Bytes()) return nil } diff --git a/cmd/tailscale/cli/up.go b/cmd/tailscale/cli/up.go index 36dcf4d86..31aac1b08 100644 --- a/cmd/tailscale/cli/up.go +++ b/cmd/tailscale/cli/up.go @@ -85,7 +85,7 @@ func acceptRouteDefault(goos string) bool { func inTest() bool { return flag.Lookup("test.v") != nil } func newUpFlagSet(goos string, upArgs *upArgsT) *flag.FlagSet { - upf := newFlagSet("up") + upf := flag.NewFlagSet("up", flag.ExitOnError) upf.BoolVar(&upArgs.qr, "qr", false, "show QR code for login URLs") upf.BoolVar(&upArgs.json, "json", false, "output in JSON format (WARNING: format subject to change)") @@ -195,7 +195,7 @@ type upOutputJSON struct { } func warnf(format string, args ...any) { - printf("Warning: "+format+"\n", args...) + fmt.Printf("Warning: "+format+"\n", args...) } var ( @@ -538,7 +538,7 @@ func runUp(ctx context.Context, args []string) (retErr error) { if env.upArgs.json { printUpDoneJSON(ipn.NeedsMachineAuth, "") } else { - fmt.Fprintf(Stderr, "\nTo authorize your machine, visit (as admin):\n\n\t%s\n\n", prefs.AdminPageURL()) + fmt.Fprintf(os.Stderr, "\nTo authorize your machine, visit (as admin):\n\n\t%s\n\n", prefs.AdminPageURL()) } case ipn.Running: // Done full authentication process @@ -546,7 +546,7 @@ func runUp(ctx context.Context, args []string) (retErr error) { printUpDoneJSON(ipn.Running, "") } else if printed { // Only need to print an update if we printed the "please click" message earlier. - fmt.Fprintf(Stderr, "Success.\n") + fmt.Fprintf(os.Stderr, "Success.\n") } select { case running <- true: @@ -575,13 +575,13 @@ func runUp(ctx context.Context, args []string) (retErr error) { fmt.Println(string(data)) } } else { - fmt.Fprintf(Stderr, "\nTo authenticate, visit:\n\n\t%s\n\n", *url) + fmt.Fprintf(os.Stderr, "\nTo authenticate, visit:\n\n\t%s\n\n", *url) if upArgs.qr { q, err := qrcode.New(*url, qrcode.Medium) if err != nil { log.Printf("QR code error: %v", err) } else { - fmt.Fprintf(Stderr, "%s\n", q.ToString(false)) + fmt.Fprintf(os.Stderr, "%s\n", q.ToString(false)) } } } @@ -695,12 +695,12 @@ func checkSSHUpWarnings(ctx context.Context) { return } if len(st.Health) == 1 && strings.Contains(st.Health[0], "SSH") { - printf("%s\n", st.Health[0]) + fmt.Printf("%s\n", st.Health[0]) return } - printf("# Health check:\n") + fmt.Printf("# Health check:\n") for _, m := range st.Health { - printf(" - %s\n", m) + fmt.Printf(" - %s\n", m) } } diff --git a/cmd/tailscale/cli/version.go b/cmd/tailscale/cli/version.go index eca3f5148..99720b169 100644 --- a/cmd/tailscale/cli/version.go +++ b/cmd/tailscale/cli/version.go @@ -18,7 +18,7 @@ ShortUsage: "version [flags]", ShortHelp: "Print Tailscale version", FlagSet: (func() *flag.FlagSet { - fs := newFlagSet("version") + fs := flag.NewFlagSet("version", flag.ExitOnError) fs.BoolVar(&versionArgs.daemon, "daemon", false, "also print local node's daemon version") return fs })(), @@ -34,16 +34,16 @@ func runVersion(ctx context.Context, args []string) error { return fmt.Errorf("too many non-flag arguments: %q", args) } if !versionArgs.daemon { - outln(version.String()) + fmt.Println(version.String()) return nil } - printf("Client: %s\n", version.String()) + fmt.Printf("Client: %s\n", version.String()) st, err := localClient.StatusWithoutPeers(ctx) if err != nil { return err } - printf("Daemon: %s\n", st.Version) + fmt.Printf("Daemon: %s\n", st.Version) return nil } diff --git a/cmd/tailscale/cli/web.go b/cmd/tailscale/cli/web.go index d53d1fda8..5702e8162 100644 --- a/cmd/tailscale/cli/web.go +++ b/cmd/tailscale/cli/web.go @@ -75,7 +75,7 @@ type tmplData struct { `), FlagSet: (func() *flag.FlagSet { - webf := newFlagSet("web") + webf := flag.NewFlagSet("web", flag.ExitOnError) 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 diff --git a/cmd/tailscaled/tailscaled.go b/cmd/tailscaled/tailscaled.go index 3ac8f8f2b..78a25321d 100644 --- a/cmd/tailscaled/tailscaled.go +++ b/cmd/tailscaled/tailscaled.go @@ -274,13 +274,6 @@ func ipnServerOpts() (o ipnserver.Options) { } switch goos { - case "js": - // The js/wasm client has no state storage so for now - // treat all interactive logins as ephemeral. - // TODO(bradfitz): if we start using browser LocalStorage - // or something, then rethink this. - o.LoginFlags = controlclient.LoginEphemeral - fallthrough default: o.SurviveDisconnects = true o.AutostartStateKey = ipn.GlobalDaemonStateKey