Hi Gerrit and other runit folks--

I'm working on a new tool that i think would fit well with runit, and i
was wondering if there is any interest in it as a contribution to the
runit suite.

The tool is a binary called "listen", which tries to open a series of
sockets and then exec()'s another command with those file descriptors
already open.  It adopts a convention for identifying those file
descriptors from systemd's socket activation features, so that it can be
used to supervise any daemon that follows the same convention.

I've attached a rough draft of the documentation for the proposed
utility -- my code doesn't implement the whole thing yet, and it's not
yet styled for inclusion in runit.  But if you think it'd be useful as
part of the runit suite, i'd be happy to try to implement it following
the runit conventions.

Also: is there a public revision control system for runit?  I've fetched
the tarballs but some of the info in the tarballs looks like it might be
generated from git (e.g. "chpst -V" produces something that looks like a
git commit id).  I'd be happy to supply changes as patches against a
canonical git repo, if there is one.

The draft of listen(1)'s man page (in markdown format) follows.

Feedback welcome,

         --dkg

listen
======

SYNOPSIS
--------

    listen [socketinfo ...] prog

where *socketinfo* is of the form:

    -family:[label]:address[,option=value...]

DESCRIPTION
-----------

The `listen` program opens the requested sockets and then execs *prog*
with those file descriptors open.  The first requested socket will be
opened on file descriptor 3, and subsequent ones follow in order.

*prog* is the first argument that does not start with a `-`.

*family* can be one of several different values.

For the following values of *family*, if *address* is a single decimal
number, it is treated as a port number and listen will bind to all
available addresses on that port.  If *address* contains a /, the part
before the / is interpreted as a network address of the requested
family, and the part after the / is treated as a port number.

    tcp: TCP on IPv4 and/or IPv6
    udp: UDP on IPv4 and/or IPv6

For the following values of *family*, *address* is interpreted as a
filesystem path.

    unix: Unix-domain streaming socket
    unix-dgram: Unix-domain datagram socket

OPTIONS
-------

Each *socketinfo* can have 0 or more options appended to it, separated
by the comma character (,) with their value appended after an equals
sign (=).

Available options are:

    backlog: Maximum queue for pending connections (see listen(2) --
             defaults to SOMAXCONN).

    mode: octal mode for unix-domain socket (defaults to relying on
          umask(2))

    user: a numeric User ID value for unix-domain socket ownership

    group: a numeric Group ID value for unix-domain socket ownership

EXIT CODES
----------

`listen` exits 100 when called with unparseable options.  It prints an
error message to stderr and exits 11 if it cannot successfully bind
all of the requested sockets.  Otherwise, its exit code is the same as
that of *prog*.

ENVIRONMENT VARIABLES
---------------------

`listen` stores the number of opened file descriptors in the
environment variable `$LISTEN_FDS`, sets `$LISTEN_PID` to getpid(2),
and stores the list of colon-separated labels in `$LISTEN_FDNAMES`.

These environment variables follow the convention understood by
libsystemd (see sd_listen_fds(3)) so it should be usable with any
socket-activated daemon that expects this behavior.

If '$VERBOSE' is set, listen will write details of what it is doing to
stderr.

EXAMPLES
--------

Run a webserver as a non-privileged user, using privileged ports, and
indicating to the webserver which ports should offer HTTPS:

    listen -tcp::80 -tcp:tls:443 chpst -u httpd webserver

Run a foregrounded (supervised) pulseaudio daemon:

    listen -unix::/run/user/1000/pulse/native,backlog=5 pulseaudio --daemonize=no

Run a network daemon only on the loopback:

    listen -tcp::127.0.0.1/9999 network-daemon

Run a public-facing network daemon with a local socket for the local
administrator to control it:

    listen -tcp::443 -unix:control:/run/xyz/control,user=1000,mode=0600 xyzd


BUGS AND LIMITATIONS
--------------------

`listen` does not do any sort of name-to-number resolution: network
addresses, user ids, group ids, and port numbers must all be specified
numerically.  Hostnames, user names, group names, service names are
not interpreted.

`listen` cannot create unix-domain socket filenames that contain a
comma (,).

`listen` produces its error messages in english and is not
internationalized.

SEE ALSO
--------

listen(2), chpst(8), sd_listen_fds(3), umask(2)

AUTHOR
------

Daniel Kahn Gillmor <d...@fifthhorseman.net>

Attachment: signature.asc
Description: PGP signature

Reply via email to