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  }