github.com/bored-engineer/go-launchd@v0.0.0-20230905041514-6aff1185c30f/libxpc.go (about) 1 //go:build darwin 2 // +build darwin 3 4 package launchd 5 6 import ( 7 "runtime" 8 "syscall" 9 "unsafe" 10 ) 11 12 // Supported is true if launchd socket activation is supported on this platform 13 const Supported = true 14 15 // As a sanity check, refuse any returned array larger than this with syscall.EINVAL 16 const maxFDs = 1 << 20 17 18 // launch_activate_socket is defined in libxpc.dylib 19 var libxpc_launch_activate_socket_trampoline_addr uintptr 20 21 //go:cgo_import_dynamic libxpc_launch_activate_socket launch_activate_socket "/usr/lib/system/libxpc.dylib" 22 23 // invokes launch_activate_socket 24 func libxpc_launch_activate_socket(name string) ([]int, error) { 25 c_name_ptr, err := syscall.BytePtrFromString(name) 26 if err != nil { 27 return nil, err 28 } 29 var c_fds_ptr *uintptr // *C.int 30 defer func() { 31 if c_fds_ptr != nil { 32 free(unsafe.Pointer(c_fds_ptr)) 33 } 34 }() 35 var c_cnt uint // C.size_t 36 res, _, _ := syscall_syscall( 37 libxpc_launch_activate_socket_trampoline_addr, 38 uintptr(unsafe.Pointer(c_name_ptr)), 39 uintptr(unsafe.Pointer(&c_fds_ptr)), 40 uintptr(unsafe.Pointer(&c_cnt)), 41 ) 42 runtime.KeepAlive(c_name_ptr) 43 if res != 0 { 44 return nil, syscall.Errno(res) 45 } else if c_cnt > maxFDs { 46 return nil, syscall.EINVAL 47 } 48 c_fds := (*[maxFDs]int)(unsafe.Pointer(c_fds_ptr)) 49 fds := make([]int, c_cnt) 50 copy(fds, (*c_fds)[0:c_cnt]) 51 return fds, nil 52 }