Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions cmd/tetherd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ package main

import (
"context"
"errors"
"flag"
"fmt"
"io"
"log"
"net"
"os"
Expand All @@ -15,12 +19,42 @@ import (
"github.com/praneethravuri/tether/pkg/protocol"
)

const usage = `usage: tetherd

tetherd takes no flags or arguments. Configure it with TETHER_SOCK and
TETHER_DB; see the README for the full list of environment variables.`

// parseArgs rejects anything on the command line: tetherd takes no flags or
// arguments. Without this, an unrecognized flag like a stray "-h" was
// silently ignored and the daemon started anyway, bound to the default
// socket -- there was no way to tell a typo from a real invocation.
func parseArgs(args []string) error {
fs := flag.NewFlagSet("tetherd", flag.ContinueOnError)
fs.SetOutput(io.Discard) // usage is printed by the caller, once, on our terms
if err := fs.Parse(args); err != nil {
return err
}
if fs.NArg() > 0 {
return fmt.Errorf("unrecognized argument %q", fs.Arg(0))
}
return nil
}

// version is overridden at build time the same way as cmd/tether's, via
// -ldflags "-X main.version=...". Logged at startup since tetherd has no
// subcommands to print it on request.
var version = "dev"

func main() {
if err := parseArgs(os.Args[1:]); err != nil {
if errors.Is(err, flag.ErrHelp) {
fmt.Println(usage)
os.Exit(0)
}
fmt.Fprintf(os.Stderr, "tetherd: %v\n%s\n", err, usage)
os.Exit(2)
}

log.SetFlags(log.LstdFlags | log.Lmsgprefix)
log.SetPrefix("tetherd: ")

Expand Down
36 changes: 36 additions & 0 deletions cmd/tetherd/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package main
import (
"context"
"encoding/json"
"errors"
"flag"
"io"
"log"
"net"
Expand All @@ -16,6 +18,40 @@ import (
"github.com/praneethravuri/tether/pkg/protocol"
)

func TestParseArgs(t *testing.T) {
cases := []struct {
name string
args []string
wantErr error // checked with errors.Is; nil means "some error"
wantOK bool
}{
{name: "no arguments", args: nil, wantOK: true},
{name: "help flag", args: []string{"-h"}, wantErr: flag.ErrHelp},
{name: "long help flag", args: []string{"--help"}, wantErr: flag.ErrHelp},
{name: "unrecognized flag", args: []string{"-x"}},
{name: "stray positional argument", args: []string{"foo"}},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
err := parseArgs(tc.args)
switch {
case tc.wantOK:
if err != nil {
t.Fatalf("parseArgs(%v) = %v, want nil", tc.args, err)
}
case tc.wantErr != nil:
if !errors.Is(err, tc.wantErr) {
t.Fatalf("parseArgs(%v) = %v, want %v", tc.args, err, tc.wantErr)
}
default:
if err == nil {
t.Fatalf("parseArgs(%v) = nil, want an error", tc.args)
}
}
})
}
}

func TestDaemonIsLive_NoSocketAtAll(t *testing.T) {
dir := shortTempDir(t)
if daemonIsLive(filepath.Join(dir, "does-not-exist")) {
Expand Down
Loading