github.com/bored-engineer/go-launchd@v0.0.0-20230905041514-6aff1185c30f/launchd.go (about) 1 package launchd 2 3 import ( 4 "fmt" 5 "net" 6 "os" 7 "syscall" 8 ) 9 10 // Files returns the *os.File for a given socket name 11 func Files(name string) ([]*os.File, error) { 12 fds, err := libxpc_launch_activate_socket(name) 13 if err != nil { 14 return nil, err 15 } 16 files := make([]*os.File, len(fds)) 17 for idx, fd := range fds { 18 files[idx] = os.NewFile(uintptr(fd), "") 19 } 20 return files, nil 21 } 22 23 // Sockets returns the net.Listener for each socket name 24 func Sockets(name string) ([]net.Listener, error) { 25 files, err := Files(name) 26 if err != nil { 27 return nil, err 28 } 29 listeners := make([]net.Listener, len(files)) 30 for idx, file := range files { 31 listener, err := net.FileListener(file) 32 if err != nil { 33 return nil, fmt.Errorf("net.FileListener for %d failed: %w", file.Fd(), err) 34 } 35 listeners[idx] = listener 36 } 37 return listeners, nil 38 } 39 40 // Activates a single net.Listener with the given socket name 41 // If anything other than a single file descriptor is available syscall.EINVAL is returned 42 func Activate(name string) (net.Listener, error) { 43 listeners, err := Sockets(name) 44 if err != nil { 45 return nil, err 46 } else if len(listeners) != 1 { 47 return nil, syscall.EINVAL 48 } 49 return listeners[0], nil 50 }