diff --git a/Makefile b/Makefile index d0f3b2c..378f2bf 100644 --- a/Makefile +++ b/Makefile @@ -42,7 +42,7 @@ dist: clean vendor build (cd "$(TMP)" && tar -cvzf "$(BIN)-$(VERSION)-src.tar.gz" "$(BIN)-$(VERSION)") mkdir "$(TMP)/$(BIN)-$(VERSION)-linux64" - cp "$(BIN)" "$(BIN).service" LICENSE README.md "$(TMP)/$(BIN)-$(VERSION)-linux64" + cp "$(BIN)" "$(BIN).service" "$(BIN).socket" LICENSE README.md "$(TMP)/$(BIN)-$(VERSION)-linux64" (cd "$(TMP)" && tar -cvzf "$(BIN)-$(VERSION)-linux64.tar.gz" "$(BIN)-$(VERSION)-linux64") mkdir -p dist @@ -60,5 +60,6 @@ dist: clean vendor build install: install -Dm755 -t "$(BIN_DIR)/" $(BIN) install -Dm644 -t "$(LIB_DIR)/systemd/user" "$(BIN).service" + install -Dm644 -t "$(LIB_DIR)/systemd/user" "$(BIN).socket" install -Dm644 -t "$(SHARE_DIR)/licenses/$(BIN)/" LICENSE install -Dm644 -t "$(SHARE_DIR)/doc/$(BIN)/" README.md diff --git a/README.md b/README.md index 40188f5..e0b0e50 100644 --- a/README.md +++ b/README.md @@ -14,13 +14,20 @@ _See also: [FAQ: Which UI components are already integrated with this app?](#faq On Arch Linux, you can install it with `pacman -S yubikey-touch-detector` -The package also installs a systemd service, make sure to start and enable it: +The package also installs a systemd service and socket. If you want the app to launch on startup, just enable the service like so: ``` $ systemctl --user daemon-reload $ systemctl --user enable --now yubikey-touch-detector.service ``` +If you want the service to be started only when there is a listener on Unix socket, enable the socket instead like so: + +``` +$ systemctl --user daemon-reload +$ systemctl --user enable --now yubikey-touch-detector.socket +``` + Alternatively you can download the latest release from the [GitHub releases](https://github.com/maximbaz/yubikey-touch-detector/releases) page. All releases are signed with [my PGP key](https://keybase.io/maximbaz). Finally you can install the app with `go`: @@ -69,7 +76,7 @@ YUBIKEY_TOUCH_DETECTOR_LIBNOTIFY=true #### Integrating with other UI components -First of all, make sure the app is always running (e.g. start a provided systemd user service). +First of all, make sure the app is always running (e.g. start a provided systemd user service or socket). Next, in order to integrate the app with other UI components to display a visible indicator, use any of the available notifiers in the `notifier` subpackage. diff --git a/go.mod b/go.mod index fbc1b1e..620096b 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/maximbaz/yubikey-touch-detector go 1.14 require ( + github.com/coreos/go-systemd/v22 v22.1.0 github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect github.com/menefotto/go-libnotify v0.0.0-20160821232856-351dc16572b9 github.com/rjeczalik/notify v0.9.2 diff --git a/go.sum b/go.sum index 94dcf45..32a11a4 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,11 @@ +github.com/coreos/go-systemd/v22 v22.1.0 h1:kq/SbG2BCKLkDKkjQf5OWwKWUKj1lgs3lFI4PxnR5lg= +github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/fatih/set v0.2.1 h1:nn2CaJyknWE/6txyUDGwysr3G5QC6xWB/PtVjPBbeaA= github.com/fatih/set v0.2.1/go.mod h1:+RKtMCH+favT2+3YecHGxcc0b4KyVWA1QWWJUs4E0CI= +github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= diff --git a/notifier/unix_socket.go b/notifier/unix_socket.go index acb7077..0b97914 100644 --- a/notifier/unix_socket.go +++ b/notifier/unix_socket.go @@ -7,6 +7,7 @@ import ( "strings" "sync" + "github.com/coreos/go-systemd/v22/activation" log "github.com/sirupsen/logrus" ) @@ -23,19 +24,33 @@ func SetupUnixSocketNotifier(notifiers *sync.Map, exits *sync.Map) { return } - socketFile := path.Join(socketDir, "yubikey-touch-detector.socket") - if _, err := os.Stat(socketFile); err == nil { - log.Warnf("'%v' already exists, assuming it's an obsolete one and trying to recover", socketFile) - if err = os.Remove(socketFile); err != nil { - log.Errorf("Cannot remove '%v' in order to recover from possible previous crash", socketFile) - return - } + listeners, err := activation.Listeners() + if err != nil { + log.Errorf("Error receiving activation listeners from systemd, proceeding to create our own unix socket: %v", err) } - socket, err := net.Listen("unix", socketFile) - if err != nil { - log.Error("Cannot establish a proxy SSH socket: ", err) - return + var socket net.Listener + if len(listeners) > 1 { + log.Warn("Received more than one listener from systemd which should not be possible, using the first one") + socket = listeners[0] + } else if len(listeners) == 1 { + socket = listeners[0] + } else { + socketFile := path.Join(socketDir, "yubikey-touch-detector.socket") + + if _, err := os.Stat(socketFile); err == nil { + log.Warnf("'%v' already exists, assuming it's obsolete and trying to recover", socketFile) + if err = os.Remove(socketFile); err != nil { + log.Errorf("Cannot remove '%v' in order to recover from possible previous crash", socketFile) + return + } + } + + socket, err = net.Listen("unix", socketFile) + if err != nil { + log.Error("Cannot establish a unix socket listener: ", err) + return + } } exit := make(chan bool) diff --git a/yubikey-touch-detector.socket b/yubikey-touch-detector.socket new file mode 100644 index 0000000..f76f2f9 --- /dev/null +++ b/yubikey-touch-detector.socket @@ -0,0 +1,9 @@ +[Unit] +Description=Unix socket activation for YubiKey touch detector service + +[Socket] +ListenStream=%t/yubikey-touch-detector.socket +RemoveOnStop=yes + +[Install] +WantedBy=sockets.target