* Author: Sam Thursfield <samthursfield@codethink.co.uk>
*/
+#include <assert.h>
+#include <string.h>
+#include <unistd.h>
#include <dbus/dbus-glib.h>
#include <dbus/dbus.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include <glib/gspawn.h>
+
#include "libmoonshot.h"
#include "libmoonshot-common.h"
+/*30 days in ms*/
+#define INFINITE_TIMEOUT 10*24*60*60*1000
+
#define MOONSHOT_DBUS_NAME "org.janet.Moonshot"
#define MOONSHOT_DBUS_PATH "/org/janet/moonshot"
{
g_free (data);
}
+static char *moonshot_launch_argv[] = {
+ MOONSHOT_LAUNCH_SCRIPT, NULL
+};
+
+static DBusConnection *dbus_launch_moonshot()
+{
+ DBusConnection *connection = NULL;
+ DBusError dbus_error;
+ GPid child_pid;
+ gint fd_stdin = -1, fd_stdout = -1;
+ ssize_t addresslen;
+ char dbus_address[1024];
+
+ if (g_spawn_async_with_pipes( NULL /*cwd*/,
+ moonshot_launch_argv, NULL /*environ*/,
+ 0 /*flags*/, NULL /*setup*/, NULL,
+ &child_pid, &fd_stdin, &fd_stdout,
+ NULL /*stderr*/, NULL /*error*/) == 0 ) {
+ return NULL;
+ }
+
+ dbus_error_init(&dbus_error);
+ addresslen = read( fd_stdout, dbus_address, sizeof dbus_address);
+ close(fd_stdout);
+ /* we require at least 2 octets of address because we trim the newline*/
+ if (addresslen <= 1) {
+ fail: dbus_error_free(&dbus_error);
+ if (connection != NULL)
+ dbus_connection_unref(connection);
+ close(fd_stdin);
+ g_spawn_close_pid(child_pid);
+ return NULL;
+ }
+ dbus_address[addresslen-1] = '\0';
+ connection = dbus_connection_open(dbus_address, &dbus_error);
+ if (dbus_error_is_set(&dbus_error)) {
+ goto fail;
+ }
+ if (!dbus_bus_register(connection, &dbus_error))
+ goto fail;
+ return connection;
+}
+
static DBusGProxy *dbus_connect (MoonshotError **error)
{
DBusError dbus_error;
DBusGConnection *g_connection;
DBusGProxy *g_proxy;
- GError *g_error;
+ GError *g_error = NULL;
dbus_bool_t name_has_owner;
g_return_val_if_fail (*error == NULL, NULL);
connection = dbus_bus_get (DBUS_BUS_SESSION, &dbus_error);
- if (dbus_error_is_set (&dbus_error)) {
+ if (dbus_error_has_name(&dbus_error, DBUS_ERROR_NOT_SUPPORTED)) {
+ /*Generally this means autolaunch failed because probably DISPLAY is unset*/
+ connection = dbus_launch_moonshot();
+ if (connection != NULL) {
+ dbus_error_free(&dbus_error);
+ dbus_error_init(&dbus_error);
+ }
+ }
+
+ if (dbus_error_is_set (&dbus_error)) {
*error = moonshot_error_new (MOONSHOT_ERROR_IPC_ERROR,
"DBus error: %s",
dbus_error.message);
/* Now the service should be running */
g_error = NULL;
- g_connection = dbus_g_bus_get (DBUS_BUS_SESSION, &g_error);
-
- if (g_error != NULL) {
- *error = moonshot_error_new (MOONSHOT_ERROR_IPC_ERROR,
- "DBus error: %s",
- g_error->message);
- g_error_free (g_error);
- return NULL;
- }
-
+ g_connection = dbus_connection_get_g_connection(connection);
+ assert (g_connection != NULL);
g_proxy = dbus_g_proxy_new_for_name_owner (g_connection,
MOONSHOT_DBUS_NAME,
MOONSHOT_DBUS_PATH,
g_return_val_if_fail (DBUS_IS_G_PROXY (dbus_proxy), FALSE);
- dbus_g_proxy_call (dbus_proxy,
+ dbus_g_proxy_call_with_timeout (dbus_proxy,
"GetIdentity",
- &g_error,
+ INFINITE_TIMEOUT,
+ &g_error,
G_TYPE_STRING, nai,
G_TYPE_STRING, password,
G_TYPE_STRING, service,
g_return_val_if_fail (DBUS_IS_G_PROXY (dbus_proxy), FALSE);
- dbus_g_proxy_call (dbus_proxy,
+ dbus_g_proxy_call_with_timeout (dbus_proxy,
"GetDefaultIdentity",
+ INFINITE_TIMEOUT,
&g_error,
G_TYPE_INVALID,
G_TYPE_STRING, nai_out,
return FALSE;
g_return_val_if_fail (DBUS_IS_G_PROXY (dbus_proxy), FALSE);
- g_return_val_if_fail (rules_patterns_length == rules_always_confirm_length), FALSE);
+ g_return_val_if_fail (rules_patterns_length == rules_always_confirm_length, FALSE);
/* Marshall array and struct parameters for DBus */
- rules_patterns_strv = g_malloc ((rules_length + 1) * sizeof (const char *));
- rules_always_confirm_strv = g_malloc ((rules_length + 1) * sizeof (const char *));
+ rules_patterns_strv = g_malloc ((rules_patterns_length + 1) * sizeof (const char *));
+ rules_always_confirm_strv = g_malloc ((rules_patterns_length + 1) * sizeof (const char *));
services_strv = g_malloc ((services_length + 1) * sizeof (const char *));
for (i = 0; i < rules_patterns_length; i ++) {
- rules_pattern_strv[i] = rules_patterns[i];
+ rules_patterns_strv[i] = rules_patterns[i];
rules_always_confirm_strv[i] = rules_always_confirm[i];
}
for (i = 0; i < services_length; i ++)
services_strv[i] = services[i];
- rules_pattern_strv[rules_patterns_length] = NULL;
+ rules_patterns_strv[rules_patterns_length] = NULL;
rules_always_confirm_strv[rules_patterns_length] = NULL;
services_strv[services_length] = NULL;
G_TYPE_STRING, user_name,
G_TYPE_STRING, password,
G_TYPE_STRING, realm,
- G_TYPE_STRV, rules_pattern_strv,
+ G_TYPE_STRV, rules_patterns_strv,
G_TYPE_STRV, rules_always_confirm_strv,
G_TYPE_STRV, services_strv,
G_TYPE_STRING, ca_cert,