diff options
author | Simon McVittie <simon.mcvittie@collabora.co.uk> | 2011-09-14 18:15:08 +0100 |
---|---|---|
committer | Simon McVittie <simon.mcvittie@collabora.co.uk> | 2011-09-14 18:15:08 +0100 |
commit | cf447c8af038d2470011c685eb391fd76ffd8f40 (patch) | |
tree | a23357ee0a27fd020ac03184b4e1bb0358869048 | |
parent | 59c6663293bbbd9399f4c16611e06bbe799ddb8a (diff) |
old WiP: inetd-style listeningwip-inetd
-rw-r--r-- | dbus/dbus-server-unix.c | 28 | ||||
-rw-r--r-- | dbus/dbus-sysdeps-unix.c | 113 |
2 files changed, 125 insertions, 16 deletions
diff --git a/dbus/dbus-server-unix.c b/dbus/dbus-server-unix.c index 70ad9654..20e2dd8d 100644 --- a/dbus/dbus-server-unix.c +++ b/dbus/dbus-server-unix.c @@ -179,7 +179,33 @@ _dbus_server_listen_platform_specific (DBusAddressEntry *entry, dbus_free (fds); return DBUS_SERVER_LISTEN_OK; - } + } + else if (strcmp (method, "inetd") == 0) + { + int fd; + DBusString address; + + fd = _dbus_listen_inetd (error); + + if (fd < 0) + { + _DBUS_ASSERT_ERROR_IS_SET (error); + return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; + } + + _dbus_string_init_const (&address, "inetd:"); + + *server_p = _dbus_server_new_for_socket (&fd, 1, &address, NULL); + + if (*server_p == NULL) + { + _dbus_close_socket (fd, NULL); + dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); + return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; + } + + return DBUS_SERVER_LISTEN_OK; + } #ifdef DBUS_ENABLE_LAUNCHD else if (strcmp (method, "launchd") == 0) { diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c index e9ea2535..58cd50e8 100644 --- a/dbus/dbus-sysdeps-unix.c +++ b/dbus/dbus-sysdeps-unix.c @@ -1028,6 +1028,102 @@ _dbus_listen_unix_socket (const char *path, return listen_fd; } +static dbus_bool_t +check_socket_is_listening_stream (int fd, + DBusError *error) +{ + /* We use systemd utility functions here: they're meant to be portable + * to non-Linux Unixes */ + r = sd_is_socket (fd, AF_UNSPEC, SOCK_STREAM, 1); + + if (r < 0) + { + dbus_set_error (error, _dbus_error_from_errno (-r), + "Failed to verify passed socket type: %s", + _dbus_strerror (-r)); + return FALSE; + } + + if (!r) + { + dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, + "Passed socket has wrong type."); + return FALSE; + } + + return TRUE; +} + +/** + * Acquires the socket that is our stdin and stdout. Reopens stdin and stdout + * from/to /dev/null, sets the socket to be nonblocking and close on exec, + * and returns the socket's new fd. + * + * @returns a socket fd, or -1 on error + */ +int +_dbus_listen_inetd (DBusError *error) +{ + int fd = -1, nullfd = -1; + + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + + if (!check_socket_is_listening_stream (STDIN_FILENO, error)) + return -1; + + if (!check_socket_is_listening_stream (STDOUT_FILENO, error)) + return -1; + + nullfd = open ("/dev/null", O_RDWR); + + if (nullfd == -1) + { + dbus_set_error (error, DBUS_ERROR_FAILED, "Failed to open /dev/null"); + goto fail; + } + + fd = _dbus_dup (STDIN_FILENO, error); + + if (fd < 0) + goto fail; + + if (dup2 (fd, STDIN_FILENO)) + { + dbus_set_error (error, DBUS_ERROR_FAILED, + "Failed to dup /dev/null to replace stdin"); + goto fail; + } + + if (dup2 (fd, STDOUT_FILENO)) + { + dbus_set_error (error, DBUS_ERROR_FAILED, + "Failed to dup /dev/null to replace stdout"); + goto fail; + } + + _dbus_close (nullfd, NULL); + nullfd = -1; + + if (!_dbus_set_local_creds (fd, TRUE)) + { + dbus_set_error (error, _dbus_error_from_errno (errno), + "Failed to enable LOCAL_CREDS on inetd socket: %s", + _dbus_strerror (errno)); + goto fail; + } + + return fd; + +fail: + if (fd >= 0) + _dbus_close (fd, NULL); + + if (nullfd >= 0) + _dbus_close (nullfd, NULL); + + return -1; +} + /** * Acquires one or more sockets passed in from systemd. The sockets * are set to be nonblocking. @@ -1066,21 +1162,8 @@ _dbus_listen_systemd_sockets (int **fds, for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) { - r = sd_is_socket (fd, AF_UNSPEC, SOCK_STREAM, 1); - if (r < 0) - { - dbus_set_error (error, _dbus_error_from_errno (-r), - "Failed to verify systemd socket type: %s", - _dbus_strerror (-r)); - return -1; - } - - if (!r) - { - dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, - "Passed socket has wrong type."); - return -1; - } + if (!check_socket_is_listening_stream (fd, error)) + return -1; } /* OK, the file descriptors are all good, so let's take posession of |