PassAGE/clipboard.go
fraggle 3552db50c2 Initial commit: PassAGE password manager
- AGE encryption with master password model
- Core commands: init, show, insert, edit, generate, rm, mv, cp, find, grep, ls
- Git integration for version control
- Clipboard support (X11 and Wayland)
- Secure password generation
- Backup and restore functionality
- Comprehensive security features
- Complete documentation
2026-01-11 18:48:01 -04:00

79 lines
2.1 KiB
Go

package main
import (
"fmt"
"os"
"os/exec"
"os/signal"
"strings"
"syscall"
"time"
)
// clearClipboardAfter clears the clipboard after a delay
// Runs in a goroutine so it doesn't block
func clearClipboardAfter(duration time.Duration) {
go func() {
time.Sleep(duration)
clearClipboard()
}()
}
// clearClipboard clears the clipboard
// Tries both Wayland and X11 - whichever is available
func clearClipboard() {
var cmd *exec.Cmd
if os.Getenv("WAYLAND_DISPLAY") != "" {
cmd = exec.Command("wl-copy", "--clear")
} else if os.Getenv("DISPLAY") != "" {
// X11 - clear by copying /dev/null (hacky but works)
cmd = exec.Command("xclip", "-selection", "clipboard", "/dev/null")
} else {
return // No clipboard available, nothing to clear
}
cmd.Run() // Best effort - if it fails, oh well
}
// clipToClipboard copies text to clipboard and sets up auto-clear
func clipToClipboard(text, path string) {
clipTime := 10
if env := os.Getenv("PASSAGE_CLIP_TIME"); env != "" {
if n, err := fmt.Sscanf(env, "%d", &clipTime); err != nil || n != 1 || clipTime < 0 || clipTime > 3600 {
clipTime = 10 // Reset to default on invalid input
}
}
// Try xclip (X11) or wl-copy (Wayland)
var cmd *exec.Cmd
if os.Getenv("WAYLAND_DISPLAY") != "" {
cmd = exec.Command("wl-copy")
} else if os.Getenv("DISPLAY") != "" {
cmd = exec.Command("xclip", "-selection", "clipboard")
} else {
fmt.Fprintf(os.Stderr, "Error: no clipboard available (needs X11 or Wayland)\n")
os.Exit(1)
}
cmd.Stdin = strings.NewReader(text)
if err := cmd.Run(); err != nil {
fmt.Fprintf(os.Stderr, "Error: failed to copy to clipboard: %v\n", err)
os.Exit(1)
}
fmt.Printf("Copied %s to clipboard. Will clear in %d seconds.\n", path, clipTime)
// Set up signal handler to clear clipboard if user hits Ctrl+C
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
// Auto-clear after the timeout
clearClipboardAfter(time.Duration(clipTime) * time.Second)
// Also clear if interrupted - don't leave passwords lying around
go func() {
<-sigChan
clearClipboard()
os.Exit(0)
}()
}