Files
wehub-resource-sync 36b3af2e3d
PR Check / Code Quality: Format (push) Failing after 1s
PR Check / Code Quality: Lint (darwin) (push) Failing after 0s
PR Check / Code Quality: Lint (freebsd) (push) Failing after 1s
PR Check / Code Quality: Lint (windows) (push) Failing after 1s
PR Check / Code Quality: Lint (linux) (push) Failing after 1s
PR Check / Security: Vulnerability Scan (push) Failing after 0s
Update Documentation / update-docs (push) Failing after 2s
PR Check / Code Quality: Vendor (push) Failing after 1s
PR Check / Code Quality: Coverage (push) Failing after 0s
PR Check / Tests: Unit (macos-latest) (push) Has been cancelled
PR Check / Tests: Unit (ubuntu-24.04) (push) Has been cancelled
PR Check / Tests: Unit (ubuntu-24.04-arm) (push) Has been cancelled
PR Check / Tests: Unit (windows-latest) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:22:06 +08:00

82 lines
1.9 KiB
Go

//go:build darwin
package source
import (
"strings"
"github.com/pranshuparmar/witr/internal/launchd"
"github.com/pranshuparmar/witr/pkg/model"
)
func detectLaunchd(ancestry []model.Process) *model.Source {
// Check if the ancestry includes launchd (PID 1)
hasLaunchd := false
for _, p := range ancestry {
if p.PID == 1 && p.Command == "launchd" {
hasLaunchd = true
break
}
}
if !hasLaunchd {
return nil
}
// Get the target process (last in ancestry)
if len(ancestry) == 0 {
return nil
}
target := ancestry[len(ancestry)-1]
// Try to get detailed launchd info for the target process
info, err := launchd.GetLaunchdInfo(target.PID)
if err != nil {
// Fall back to basic launchd detection
return &model.Source{
Type: model.SourceLaunchd,
Name: "launchd",
}
}
// Build the source with details
source := &model.Source{
Type: model.SourceLaunchd,
Name: info.Label,
Description: info.Comment,
Details: make(map[string]string),
}
// Add domain description (Launch Agent vs Launch Daemon)
source.Details["type"] = info.DomainDescription()
// Add plist path if found
if info.PlistPath != "" {
source.UnitFile = info.PlistPath
source.Details["plist"] = info.PlistPath
}
// Separate schedule triggers from non-schedule triggers
var scheduleParts, triggerParts []string
for _, t := range info.FormatTriggers() {
if strings.HasPrefix(t, "StartInterval") || strings.HasPrefix(t, "StartCalendarInterval") {
scheduleParts = append(scheduleParts, t)
} else {
triggerParts = append(triggerParts, t)
}
}
if len(scheduleParts) > 0 {
source.Details["schedule"] = strings.Join(scheduleParts, "; ")
}
if len(triggerParts) > 0 {
source.Details["triggers"] = strings.Join(triggerParts, "; ")
}
// Add KeepAlive status
if info.KeepAlive {
source.Details["keepalive"] = "Yes (restarts if killed)"
}
return source
}