| package report |
|
|
| import ( |
| "fmt" |
| "os" |
| "os/exec" |
| "os/user" |
| "path/filepath" |
| "runtime" |
| "strings" |
| ) |
|
|
| var daemonExecCommand = exec.Command |
|
|
| func IsDaemonInstalled() bool { |
| manager, err := currentDaemonManager() |
| if err != nil { |
| return false |
| } |
| _, err = os.Stat(manager.ServicePath()) |
| return err == nil |
| } |
|
|
| func IsDaemonRunning() bool { |
| manager, err := currentDaemonManager() |
| if err != nil { |
| return false |
| } |
| status, err := manager.Status() |
| if err != nil { |
| return false |
| } |
| return daemonStatusLooksRunning(status) |
| } |
|
|
| |
| type daemonInfo struct { |
| osName string |
| userID string |
| } |
|
|
| func currentDaemonManager() (daemonService, error) { |
| u, err := user.Current() |
| if err != nil { |
| return nil, err |
| } |
| info := daemonInfo{osName: runtime.GOOS, userID: u.Uid} |
| switch info.osName { |
| case "linux": |
| return &systemdStatus{userID: u.Uid}, nil |
| case "darwin": |
| return &launchdStatus{userID: u.Uid}, nil |
| default: |
| return nil, fmt.Errorf("unsupported OS") |
| } |
| } |
|
|
| type daemonService interface { |
| ServicePath() string |
| Status() (string, error) |
| } |
|
|
| type systemdStatus struct{ userID string } |
|
|
| func (s *systemdStatus) ServicePath() string { |
| if configHome := strings.TrimSpace(os.Getenv("XDG_CONFIG_HOME")); configHome != "" { |
| return filepath.Join(configHome, "systemd", "user", "pinchtab.service") |
| } |
| home, _ := os.UserHomeDir() |
| return filepath.Join(home, ".config", "systemd", "user", "pinchtab.service") |
| } |
| func (s *systemdStatus) Status() (string, error) { |
| return runDaemonCommand("systemctl", "--user", "status", "pinchtab.service", "--no-pager") |
| } |
|
|
| type launchdStatus struct{ userID string } |
|
|
| func (s *launchdStatus) ServicePath() string { |
| home, _ := os.UserHomeDir() |
| return filepath.Join(home, "Library", "LaunchAgents", "com.pinchtab.pinchtab.plist") |
| } |
| func (s *launchdStatus) Status() (string, error) { |
| return runDaemonCommand("launchctl", "print", "gui/"+s.userID+"/com.pinchtab.pinchtab") |
| } |
|
|
| func runDaemonCommand(name string, args ...string) (string, error) { |
| cmd := daemonExecCommand(name, args...) |
| output, err := cmd.CombinedOutput() |
| trimmed := strings.TrimSpace(string(output)) |
| if err == nil { |
| return trimmed, nil |
| } |
| if trimmed == "" { |
| return "", fmt.Errorf("%s %s: %w", name, strings.Join(args, " "), err) |
| } |
| return "", fmt.Errorf("%s %s: %w: %s", name, strings.Join(args, " "), err, trimmed) |
| } |
|
|
| func daemonStatusLooksRunning(status string) bool { |
| return strings.Contains(status, "state = running") || |
| strings.Contains(status, "Active: active (running)") |
| } |
|
|