lockbox

password manager
Log | Files | Refs | README | LICENSE

commit 4f250f04cf94416445369fb917ae3b6d38ad2c78
parent 34d9312ab26a5eaa3e089c1e90f7faa447de8211
Author: Sean Enck <sean@ttypty.com>
Date:   Sun, 29 Jun 2025 22:23:42 -0400

fixing some clipboard manager components

Diffstat:
Minternal/config/vars.go | 1+
Minternal/platform/clipmanager.go | 41+++++++++++++++++++++++++++++++++++------
Minternal/platform/clipmanager_test.go | 26++++++++++++++++++++++++++
3 files changed, 62 insertions(+), 6 deletions(-)

diff --git a/internal/config/vars.go b/internal/config/vars.go @@ -51,6 +51,7 @@ var ( description: "Set the pidfile for clipboard management", }), allowed: []string{fileExample}, + flags: []stringsFlags{canExpandFlag}, }, }) // EnvJSONHashLength handles the hashing output length diff --git a/internal/platform/clipmanager.go b/internal/platform/clipmanager.go @@ -6,7 +6,9 @@ import ( "fmt" "os" "os/exec" + "strconv" "strings" + "syscall" "time" "git.sr.ht/~enckse/lockbox/internal/app/commands" @@ -23,6 +25,7 @@ type ( Copy(Clipboard, string) Sleep() Loader() ClipboardLoader + Checkpid(int) error } // DefaultClipboardDaemon is the default functioning daemon DefaultClipboardDaemon struct{} @@ -68,6 +71,15 @@ func (d DefaultClipboardDaemon) Loader() ClipboardLoader { return DefaultClipboardLoader{Full: true} } +// Checkpid will check if a pid is still active +func (d DefaultClipboardDaemon) Checkpid(pid int) error { + process, err := os.FindProcess(pid) + if err != nil { + return err + } + return process.Signal(syscall.Signal(0)) +} + // ClipboardManager handles the daemon runner func ClipboardManager(daemon bool, manager ClipboardDaemon) error { if manager == nil { @@ -80,7 +92,28 @@ func ClipboardManager(daemon bool, manager ClipboardDaemon) error { if clipboard.PIDFile == "" { return errors.New("pidfile is unset") } + getProcess := func() (string, error) { + b, err := manager.ReadFile(clipboard.PIDFile) + if err != nil { + return "", err + } + val := strings.TrimSpace(string(b)) + return val, nil + } if !daemon { + if PathExists(clipboard.PIDFile) { + p, err := getProcess() + if err != nil { + return err + } + pid, err := strconv.Atoi(p) + if err != nil { + return err + } + if err := manager.Checkpid(pid); err == nil { + return nil + } + } return manager.Start(commands.Executable, commands.ClipManagerDaemon) } paste, pasteArgs, err := clipboard.Args(false) @@ -104,12 +137,8 @@ func ClipboardManager(daemon bool, manager ClipboardDaemon) error { } pid := strings.TrimSpace(fmt.Sprintf("%d", manager.Getpid())) isCurrentProcess := func() (bool, error) { - b, err := manager.ReadFile(clipboard.PIDFile) - if err != nil { - return false, err - } - val := strings.TrimSpace(string(b)) - return val == pid, nil + val, err := getProcess() + return val == pid, err } manager.WriteFile(clipboard.PIDFile, pid) var errs []error diff --git a/internal/platform/clipmanager_test.go b/internal/platform/clipmanager_test.go @@ -3,6 +3,8 @@ package platform_test import ( "errors" "fmt" + "os" + "path/filepath" "strings" "testing" @@ -62,6 +64,10 @@ func (d *mock) Loader() platform.ClipboardLoader { return mockLoader{name: "linux", runtime: "linux"} } +func (d *mock) Checkpid(_ int) error { + return d.err +} + func TestErrors(t *testing.T) { store.Clear() defer store.Clear() @@ -92,6 +98,26 @@ func TestStart(t *testing.T) { if m.cmd != "lb" || fmt.Sprintf("%v", m.args) != "[clipmgrd]" { t.Errorf("invalid calls: %s %v", m.cmd, m.args) } + pidFile := "testdata" + os.MkdirAll(pidFile, 0o755) + pidFile = filepath.Join("testdata", "pidfile") + store.SetString("LOCKBOX_CLIP_PIDFILE", pidFile) + os.WriteFile(pidFile, []byte("123"), 0o644) + defer os.Remove(pidFile) + m.cmd = "" + m.args = []string{} + if err := platform.ClipboardManager(false, m); err == nil || !strings.Contains(err.Error(), "Atoi") { + t.Errorf("invalid error: %v", err) + } + m.data = "1234" + m.cmd = "" + m.args = []string{} + if err := platform.ClipboardManager(false, m); err != nil { + t.Errorf("invalid error: %v", err) + } + if m.cmd != "" || fmt.Sprintf("%v", m.args) != "[]" { + t.Errorf("invalid calls: %s %v", m.cmd, m.args) + } } func TestPIDMismatch(t *testing.T) {