##
# Launch is a wrapper for the launch(3) API for daemons and agents spawned by
# launchd(8).
#
# Launch agents and daemons MUST NOT:
#
# * Call daemon(3)
# * Do the equivalent of daemon(3) by calling fork and having the parent exit
#
# Launch agents and daemons SHOULD NOT do the following as part of their
# starup initialization:
#
# * Set the user ID or group ID (Process::Sys.setuid, Process::Sys.setgid and
# friends)
# * Setup the working directory (Dir.chdir)
# * chroot(2)
# * setsid(2) (Process.setsid)
# * Close "stray" file descriptors
# * Change stdio(3) to /dev/null (STDOUT.reopen and friends)
# * Setup resource limits with setrusage (Process.setrlimit)
# * Ignore the SIGTERM signal (trap 'TERM', 'IGNORE')
#
# The above is from launchd.plist(5). Please read it for further details.
#
# To shut down cleanly trap 'TERM' and perform any shutdown steps
# before exiting.
module Launch
##
# The version of launch you are using
VERSION = '1.0'
##
# Checks in with launch and retrieves the agent's configuration. The
# configuration can be retrieved later through @launch_checkin.
def launch_checkin
response = launch_message Launch::Key::CHECKIN
return if response.nil?
@launch_checkin = response
end
##
# Creates ruby sockets from the sockets list in +name+.
# socket_class.for_fd is called for each socket in the named list.
#
# +name+ comes from the socket's name key in the launchd plist.
#
# Example plist Sockets dictionary:
#
# Sockets
#
# EchoSocket
#
# SockServiceName
# 12345
#
#
#
# Example call:
#
# servers = launch_sockets 'Echo', TCPServer
#
# p servers.map { |server| server.addr }
def launch_sockets name, socket_class
require 'socket'
sockets = @launch_checkin[Launch::JobKey::SOCKETS][name]
raise Error, "no sockets found for #{name.inspect}" unless sockets
sockets.map do |fd|
socket_class.for_fd fd
end
end
end
require 'launch/launch'
require 'socket'