Пример #1
0
JoyDBus *
joy_dbus_new(JoyApplication *app, const gchar *address, GError **error)
{
	joy_return_error_if_fail(JOY_IS_APPLICATION(app), NULL, error);
	joy_return_error_if_fail(address, NULL, error);
	DBusError dbus_error;
	dbus_error_init(&dbus_error);
	DBusConnection *connection = dbus_connection_open_private(address,
			&dbus_error);
	if (!connection) {
		g_set_error(error, JOY_ERROR, JOY_ERROR_DBUS,
				"%s", dbus_error.message);
		goto error;
	}
	if (!dbus_bus_register(connection, &dbus_error)) {
		g_set_error(error, JOY_ERROR, JOY_ERROR_DBUS,
				"%s", dbus_error.message);
		goto error;
	}
	JoyDBus *self = g_object_new(JOY_TYPE_DBUS,
			"application", app,
			"connection", connection,
			NULL);
	if (!self) {
		g_set_error_literal(error, JOY_ERROR, JOY_ERROR_NO_MEMORY,
				Q_("out of memory"));
		goto error;
	}
	if (!dbus_connection_set_watch_functions(connection, add, remove,
				toggled, self, NULL)) {
		g_set_error_literal(error, JOY_ERROR, JOY_ERROR_NO_MEMORY,
				Q_("out of memory"));
		goto error;
	}
	return self;
error:
	dbus_error_free(&dbus_error);
	if (connection) {
		if (dbus_connection_get_is_connected(connection)) {
			dbus_connection_close(connection);
		}
		dbus_connection_unref(connection);
	}
	return NULL;
}
Пример #2
0
static DBusConnection *
connect_to_bus (const gchar *address)
{
  DBusConnection *conn;
  DBusError error = DBUS_ERROR_INIT;
  dbus_bool_t ok;

  conn = dbus_connection_open_private (address, &error);
  assert_no_error (&error);
  g_assert (conn != NULL);

  ok = dbus_bus_register (conn, &error);
  assert_no_error (&error);
  g_assert (ok);
  g_assert (dbus_bus_get_unique_name (conn) != NULL);

  dbus_connection_setup_with_g_main (conn, NULL);
  return conn;
}
Пример #3
0
struct DBusConnection *
test_dbus_setup_mock(TALLOC_CTX *mem_ctx,
                     struct tevent_context *loop,
                     sbus_server_conn_init_fn init_fn,
                     void *init_pvt_data)
{
    struct mock_server *mock;
    char dummy;

    mock = talloc_zero(mem_ctx, struct mock_server);
    talloc_set_destructor(mock, mock_server_cleanup);
    mock->init_fn = init_fn;
    mock->init_pvt_data = init_pvt_data;

    mock->temp_dir = mkdtemp(talloc_strdup(mock, "/tmp/sssd-dbus-tests.XXXXXX"));
    verify_neq (mock->temp_dir, NULL);
    mock->dbus_address = talloc_asprintf(mock, "unix:path=%s/sbus", mock->temp_dir);
    verify_neq (mock->dbus_address, NULL);

    /* We use an fd pair as a synchronization device, integrates with tevent well */
    verify_eq (socketpair(PF_LOCAL, SOCK_STREAM, 0, mock->sync_fds), 0);

    /* Run the dbus server in a child process */
    mock->pid = fork();
    if (mock->pid == 0) {
        mock_server_child(mock);
        _exit(0);
    }

    verify_neq (mock->pid, -1);

    /* Synchronization point: wait for sync point in mock_server_child */
    verify_eq (read(mock->sync_fds[0], &dummy, 1), 1);

    /* Open a shared D-BUS connection to the address */
    mock->client = dbus_connection_open_private(mock->dbus_address, NULL);
    verify_neq (mock->client, NULL);

    /* Synchronization point: wait for sync point in on_accept_connection */
    verify_eq (read(mock->sync_fds[0], &dummy, 1), 1);

    return mock->client;
}
Пример #4
0
DBusConnection *
test_connect_to_bus (TestMainContext *ctx,
    const gchar *address)
{
  DBusConnection *conn;
  DBusError error = DBUS_ERROR_INIT;
  dbus_bool_t ok;

  conn = dbus_connection_open_private (address, &error);
  test_assert_no_error (&error);
  g_assert (conn != NULL);

  ok = dbus_bus_register (conn, &error);
  test_assert_no_error (&error);
  g_assert (ok);
  g_assert (dbus_bus_get_unique_name (conn) != NULL);

  test_connection_setup (ctx, conn);
  return conn;
}
Пример #5
0
bool cgm_dbus_connect(void)
{
	DBusError dbus_error;
	static DBusConnection *connection;

	dbus_error_init(&dbus_error);

	connection = dbus_connection_open_private(CGMANAGER_DBUS_SOCK, &dbus_error);
	if (!connection) {
		fprintf(stderr, "Failed opening dbus connection: %s: %s\n",
				dbus_error.name, dbus_error.message);
		dbus_error_free(&dbus_error);
		return false;
	}
	dbus_connection_set_exit_on_disconnect(connection, FALSE);
	dbus_error_free(&dbus_error);
	cgroup_manager = nih_dbus_proxy_new(NULL, connection,
				NULL /* p2p */,
				"/org/linuxcontainers/cgmanager", NULL, NULL);
	dbus_connection_unref(connection);
	if (!cgroup_manager) {
		NihError *nerr;
		nerr = nih_error_get();
		fprintf(stderr, "Error opening cgmanager proxy: %s\n", nerr->message);
		nih_free(nerr);
		cgm_dbus_disconnect();
		return false;
	}

	// get the api version
	if (cgmanager_get_api_version_sync(NULL, cgroup_manager, &api_version) != 0) {
		NihError *nerr;
		nerr = nih_error_get();
		fprintf(stderr, "Error cgroup manager api version: %s\n", nerr->message);
		nih_free(nerr);
		cgm_dbus_disconnect();
		return false;
	}

	return true;
}
Пример #6
0
DBusConnection *
test_try_connect_to_bus (TestMainContext *ctx,
    const gchar *address,
    GError **gerror)
{
  DBusConnection *conn;
  DBusError error = DBUS_ERROR_INIT;

  conn = dbus_connection_open_private (address, &error);

  if (conn == NULL)
    goto fail;

  if (!dbus_bus_register (conn, &error))
    goto fail;

  g_assert (dbus_bus_get_unique_name (conn) != NULL);

  if (ctx != NULL && !test_connection_try_setup (ctx, conn))
    {
      _DBUS_SET_OOM (&error);
      goto fail;
    }

  return conn;

fail:
  if (gerror != NULL)
    *gerror = g_dbus_error_new_for_dbus_error (error.name, error.message);

  if (conn != NULL)
    {
      dbus_connection_close (conn);
      dbus_connection_unref (conn);
    }

  dbus_error_free (&error);
  return FALSE;
}
Пример #7
0
IBusConnection *
ibus_connection_open_private (const gchar *address)
{
    g_assert (address != NULL);

    DBusError error;
    DBusConnection *dbus_connection;
    IBusConnection *connection;

    dbus_error_init (&error);
    dbus_connection = dbus_connection_open_private (address, &error);
    if (dbus_connection == NULL) {
        g_warning ("Connect to %s failed. %s.", address, error.message);
        dbus_error_free (&error);
        return NULL;
    }

    connection = ibus_connection_new ();
    ibus_connection_set_connection (connection, dbus_connection, FALSE);

    return connection;
}
int main()
{
 DBusServer* server;
	DBusConnection* connection;
	DBusError error;
	char* address;
		
	dbus_error_init(&error);
	server = dbus_server_listen("tcp:host=localhost,port=8085", &error);
	
	if(!server)
	{
		std_log(LOG_FILENAME_LINE, "Error :: %s\n%s",error.name,error.message);
		std_log(LOG_FILENAME_LINE, "Fail");
		create_xml(1);
		return 1;
	}
	
	address = dbus_server_get_address(server);
	std_log(LOG_FILENAME_LINE, "Address :; %s",address);
	
	
	connection = dbus_connection_open_private("tcp:host=localhost,port=8085", &error);
	if(!CheckConnection(connection, &error))
		return 1;
	

	dbus_connection_close(connection);
	dbus_connection_unref(connection);
	dbus_shutdown();
	
	dbus_server_disconnect(server);	
	
	std_log(LOG_FILENAME_LINE, "SUCCESS");
	
	create_xml(0);
	return 0;
}
Пример #9
0
/* Constructor */
static PyObject *
Connection_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
{
    DBusConnection *conn;
    const char *address;
    PyObject *address_or_conn;
    DBusError error;
    PyObject *self, *mainloop = NULL;
    static char *argnames[] = {"address", "mainloop", NULL};

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", argnames,
                                     &address_or_conn, &mainloop)) {
        return NULL;
    }

    if (DBusPyLibDBusConnection_CheckExact(address_or_conn)) {
        DBusPyLibDBusConnection *wrapper =
            (DBusPyLibDBusConnection *) address_or_conn;

        DBUS_PY_RAISE_VIA_NULL_IF_FAIL(wrapper->conn);

        conn = dbus_connection_ref (wrapper->conn);
    }
    else if ((address = PyString_AsString(address_or_conn)) != NULL) {
        dbus_error_init(&error);

        /* We always open a private connection (at the libdbus level). Sharing
         * is done in Python, to keep things simple. */
        Py_BEGIN_ALLOW_THREADS
        conn = dbus_connection_open_private(address, &error);
        Py_END_ALLOW_THREADS

        if (!conn) {
            DBusPyException_ConsumeError(&error);
            return NULL;
        }
    }
Пример #10
0
int sss_sudo_make_request(struct sudo_result_contents ** sudo_result_out)
{


    char ** command_array,**ui;
    int err_status,count;
    dbus_uint32_t header,command_array_out_size;
    struct sudo_result_contents * sudo_result = NULL;

    DBusConnection* conn;
    DBusError err;

    DBusMessage* dbus_msg;
    DBusMessage* dbus_reply;
    DBusMessageIter msg_iter;

    dbus_bool_t ret = -1;

    fprintf(stdout,"Sending message\n");

    if(validate_message_content() !=  SSS_SUDO_VALIDATION_SUCCESS) {
        return SSS_SUDO_VALIDATION_ERR;
    }


    err_status = create_env_hash_table(msg.user_env,&msg.env_table);
    if(err_status != HASH_SUCCESS) {
        fprintf(stderr, "ccouldn't create table: %s\n", hash_error_string(err_status));
        return SSS_SUDO_MESSAGE_ERR;
    }


    err_status = create_settings_hash_table(&msg.settings_table);
    if(err_status != HASH_SUCCESS) {
        fprintf(stderr, "ccouldn't create table: %s\n", hash_error_string(err_status));
        return SSS_SUDO_MESSAGE_ERR;
    }

    /* initialise the errors */
    dbus_error_init(&err);

    /* connect to the system bus and check for errors */
    conn = dbus_connection_open_private(SSS_SUDO_SERVICE_PIPE, &err);

    if (dbus_error_is_set(&err)) {
        fprintf(stderr, "Connection Error (%s)\n", err.message);
        dbus_error_free(&err);
        return SSS_SUDO_CONNECTION_ERR;
    }
    if (NULL == conn) {
        return SSS_SUDO_CONNECTION_ERR;
    }


    /* create a new method call and check for errors */
    dbus_msg = dbus_message_new_method_call( NULL, 		               /*    target    */
                                             SUDO_SERVER_PATH,        /*    object    */
                                             SUDO_SERVER_INTERFACE,  /*   interface  */
                                             SUDO_METHOD_QUERY);    /*  method name */
    if (NULL == dbus_msg) {
        fprintf(stderr, "Message Null\n");
        free_connection(conn,&err,msg.settings_table,(DBusMessage *)NULL,(DBusMessage *)NULL);
        return SSS_SUDO_MESSAGE_ERR;
    }

    /* append arguments */


    dbus_message_iter_init_append(dbus_msg, &msg_iter);
    if(dbus_error_is_set(&err)){
        fprintf(stderr, "Failed to initialize the iterator.\n");
        free_connection(conn,&err,msg.settings_table,dbus_msg,(DBusMessage *)NULL);
        return SSS_SUDO_MESSAGE_ERR;
    }

    ret = frame_sudo_message(conn,
                             &err,
                             dbus_msg,
                             &msg,
                             &msg_iter);
    if( ret != SSS_SUDO_MESSAGE_OK){
        sudo_log(SUDO_CONV_ERROR_MSG,"Failed to frame the message to sssd -  Fatal (Access denied)\n");
        free_connection(conn,&err,(hash_table_t *)NULL,dbus_msg,(DBusMessage *)NULL);
        return SSS_SUDO_MESSAGE_ERR;
    }

    /* send message and get a handle for a reply */
    dbus_reply = dbus_connection_send_with_reply_and_block (conn,dbus_msg,
                                                            SUDO_CLIENT_TIMEOUT,
                                                            &err);
    fprintf(stdout,"Request Sent\n");
    if (dbus_error_is_set(&err)) {
        fprintf(stderr, "Connection send-reply Error (%s)\n", err.message);
        free_connection(conn,&err,(hash_table_t *)NULL,dbus_msg,(DBusMessage *)NULL);
        return SSS_SUDO_REPLY_ERR;
    }
    if (NULL == dbus_reply) {
        fprintf(stderr, "reply failed\n");
        free_connection(conn,&err,(hash_table_t *)NULL,dbus_msg,(DBusMessage *)NULL);
        return SSS_SUDO_REPLY_ERR;
    }
    sudo_result= (struct sudo_result_contents *)malloc(sizeof(struct sudo_result_contents));

    ret = get_reply_message(conn,
                            &err,
                            dbus_msg,
                            dbus_reply,
                            sudo_result,
                            &msg_iter);
    if(ret != SSS_SUDO_REPLY_OK){

    }

    /* free connection now */
    free_connection(conn,&err,(hash_table_t *)NULL,dbus_msg,dbus_reply);
    *sudo_result_out = sudo_result;
    return SSS_SUDO_SEND_AND_RECIEVE_OK;
}
Пример #11
0
DBusConnection* DBus::connection_open_private(const char *address,
                                              DBusError *error) {
  BOOST_LOG_TRIVIAL(debug) << "dbus::detail::DBus::dbus_connection_open_private: Function call";
  return dbus_connection_open_private(address, error);
}
Пример #12
0
//! Main loop
int
loop_exec()
{
    /*!
     * This is the main loop function.
     *
     * Based on code written by Kimmo.Hamalainen at nokia.com
     * http://lists.freedesktop.org/archives/dbus/2007-October/008859.html
     *
     * @return 0 on success, -1 on error
     */

    DBusError bus_error;
    dbus_error_init(&bus_error);

    // Connect to D-Bus
    bus_conn = dbus_connection_open_private(config_server_address, &bus_error);
    if (dbus_error_is_set(&bus_error)) {
        log_error("Error while connecting to the bus: %s\n", bus_error.message);
        dbus_error_free(&bus_error);
        return -1;
    }

    if (!dbus_bus_register(bus_conn, &bus_error)) {
        log_error("Error while registering to the bus: %s\n", bus_error.message);
        dbus_error_free(&bus_error);
        return -1;
    }

    config_unique_address = dbus_bus_get_unique_name(bus_conn);
    log_debug("Connected to D-Bus, unique id is %s\n", dbus_bus_get_unique_name(bus_conn));

    // Request a name (example: com.server.test)
    dbus_bus_request_name(bus_conn, config_service_name, DBUS_NAME_FLAG_REPLACE_EXISTING, &bus_error);
    if (dbus_error_is_set(&bus_error)) {
        log_error("Name Error (%s)\n", bus_error.message);
        dbus_error_free(&bus_error);
        return -1;
    }

    log_debug("Registered name '%s'\n", config_service_name);

    // Register watch callback functions
    if (!dbus_connection_set_watch_functions(bus_conn, add_watch, remove_watch, NULL, NULL, NULL)) {
        log_error("dbus_connection_set_watch_functions failed\n");
        return -1;
    }

    // Register function that handles D-Bus events (calls, signals, ...)
    if (!dbus_connection_add_filter(bus_conn, filter_func, NULL, NULL)) {
        log_error("Failed to register signal handler callback\n");
        return -1;
    }

    // Catch all method calls
    dbus_bus_add_match(bus_conn, "type='method_call'", NULL);

    log_info("Listening for connections...\n");

    /* This clears any pending messages avoiding weird timeouts on some systems
     * with dbus >= 1.2.22
     */
    while (dbus_connection_dispatch(bus_conn) == DBUS_DISPATCH_DATA_REMAINS);

    while (1) {
        struct pollfd fds[MAX_FDS];
        DBusWatch *watches[MAX_WATCHES];
        int i, j;
        int nr_fds = 0;
        int nr_watches = 0;
        int poll_result;

        // Add D-Bus watch descriptors to the list
        nr_fds = 0;
        for (i = 0; i < bus_nr_watches; i++) {
            if (bus_fds[i].fd == 0 || !dbus_watch_get_enabled(bus_watches[i])) {
                continue;
            }

            fds[nr_fds].fd = bus_fds[i].fd;
            fds[nr_fds].events = bus_fds[i].events;
            fds[nr_fds].revents = 0;
            watches[nr_fds] = bus_watches[i];
            nr_fds++;
            if (i > MAX_WATCHES) {
                log_error("ERR: %d watches reached\n", MAX_WATCHES);
                break;
            }
        }
        nr_watches = nr_fds;

        // Add subprocess descriptors to the list
        for (i = 0; i < my_proc.nr_children; i++) {
            fds[nr_fds].fd = my_proc.children[i].from;
            fds[nr_fds].events = 0;
            fds[nr_fds].revents = 0;
            nr_fds++;
        }

        // Poll descriptors
        poll_result = 0;

        if (config_timeout == 0) {
            // If no timeout defined, wait forever.
            poll_result = poll(fds, nr_fds, -1);
        }
        else {
            // wait <timeout> seconds
            poll_result = poll(fds, nr_fds, config_timeout * 1000);
        }

        if (poll_result == 0) {
            if (config_timeout != 0 && my_proc.nr_children == 0) {
                log_info("Service was idle for more than %d second(s), closing daemon...\n", config_timeout);
                break;
            }
            continue;
        }
        else if (poll_result < 0) {
            perror("poll");
            return -1;
        }

        // Iterate over all descriptors
        for (i = 0; i < nr_fds; i++) {
            if (i < nr_watches) {
                // D-Bus watch event
                if (fds[i].revents) {
                    // Handle D-Bus watch event
                    fd_handler(fds[i].revents, watches[i]);
                }
            } else {
                // Subprocess event
                for (j = 0; j < my_proc.nr_children; j++) {
                    if (my_proc.children[j].from == fds[i].fd) {
                        if (fds[i].revents) {
                            // Subprocess exited, remove it
                            rem_child(j);
                        }
                        break;
                    }
                }
            }
        }
    }

    return 0;
}
Пример #13
0
int main(int argc, char *argv[]) {
        DBusError error;
        DBusConnection *bus = NULL;
        DBusMessage *m = NULL;
        int r = EXIT_FAILURE;

        dbus_error_init(&error);

        if (argc != 2) {
                log_error("Incorrect number of arguments.");
                goto finish;
        }

        log_set_target(LOG_TARGET_AUTO);
        log_parse_environment();
        log_open();

        /* We send this event to the private D-Bus socket and then the
         * system instance will forward this to the system bus. We do
         * this to avoid an activation loop when we start dbus when we
         * are called when the dbus service is shut down. */

        if (!(bus = dbus_connection_open_private("unix:path=/run/systemd/private", &error))) {
#ifndef LEGACY
                dbus_error_free(&error);

                /* Retry with the pre v21 socket name, to ease upgrades */
                if (!(bus = dbus_connection_open_private("unix:abstract=/org/freedesktop/systemd1/private", &error))) {
#endif
                        log_error("Failed to get D-Bus connection: %s", bus_error_message(&error));
                        goto finish;
                }
#ifndef LEGACY
        }
#endif

        if (bus_check_peercred(bus) < 0) {
                log_error("Bus owner not root.");
                goto finish;
        }

        if (!(m = dbus_message_new_signal("/org/freedesktop/systemd1/agent", "org.freedesktop.systemd1.Agent", "Released"))) {
                log_error("Could not allocate signal message.");
                goto finish;
        }

        if (!dbus_message_append_args(m,
                                      DBUS_TYPE_STRING, &argv[1],
                                      DBUS_TYPE_INVALID)) {
                log_error("Could not attach group information to signal message.");
                goto finish;
        }

        if (!dbus_connection_send(bus, m, NULL)) {
                log_error("Failed to send signal message on private connection.");
                goto finish;
        }

        r = EXIT_SUCCESS;

finish:
        if (bus) {
                dbus_connection_flush(bus);
                dbus_connection_close(bus);
                dbus_connection_unref(bus);
        }

        if (m)
                dbus_message_unref(m);

        dbus_error_free(&error);
        return r;
}
Пример #14
0
static struct DriverConnection *CreateConnection(void) {
  struct DriverConnection *conn = &g_conn;
  /* Create socket for bootstrap communication with child */
  int socket_fds[2] = {-1, -1};
  int rc = socketpair(AF_UNIX, SOCK_STREAM, 0, socket_fds);
  if (rc < 0) {
    error_("failed to open sockets, errno=%d (%s)", errno, strerror(errno));
    return NULL;
  }

  api_("CreateConnection(g_exe_fd=%d, '%s')", g_exe_fd, g_exe_file);

  conn->pid = fork();
  if (conn->pid < 0) {
    error_("failed to fork, errno=%d (%s)", errno, strerror(errno));
    return NULL;
  }

  if (conn->pid == 0) {
    /* Child process: run the driver */
    close(socket_fds[0]);
    RunDriver(g_exe_fd, g_exe_file, socket_fds[1]);
  }

  /* Read bootstrap information back from the child */
  /* First: uint32_t len, char server_add[len] */
  uint32_t len;
  rc = read(socket_fds[0], &len, sizeof(len));
  assert (rc == sizeof(len));
  char *server_address = (char *)malloc(len);
  rc = read(socket_fds[0], server_address, len);
  assert (rc == len);
  /* Second: uint64_t nonce (used to confirm that the D-Bus connection we set up
   * later is indeed to the child process */
  uint64_t nonce;
  rc = read(socket_fds[0], &nonce, sizeof(nonce));
  assert (rc == sizeof(nonce));
  verbose_("started child process %d, read socket name '%s', nonce %ld",
           conn->pid, server_address, nonce);
  close(socket_fds[0]);
  close(socket_fds[1]);
  snprintf(conn->objpath, 20, "/nonce/%ld", nonce);

  /* Initialize D-Bus private connection; use the nonce as the object address */
  DBusError err;
  dbus_error_init(&err);
  conn->dbus = dbus_connection_open_private(server_address, &err);
  if (!conn->dbus) {
    error_("!!! dbus_connection_open_private failed: %s: %s\n", err.name, err.message);
    free(server_address);
    DestroyConnection(conn);
    return NULL;
  }
  log_("got connection %p to private bus '%s' with {pid=%d dbus_conn=%p objpath='%s'})",
       conn, server_address, conn->pid, conn->dbus, conn->objpath);
  free(server_address);

  /* Send a no-op message to work around a D-Bus problem (if the first message sent
     includes a file descriptor, it fails). */
  DBusMessage *req = ConnectionNewRequest(conn, "__noop");
  DBusMessage *rsp = ConnectionBlockingSendReply(conn, req, &err);
  if (rsp == NULL) {
    DestroyConnection(conn);
    return NULL;
  }
  dbus_message_unref(rsp);

  return conn;
}
Пример #15
0
/*
 * open()
 *
 * argument 1: uri to connect to
 */
static int
bus_open(lua_State *T)
{
	const char *uri;
	DBusError err;
	DBusConnection *conn;
	struct bus_object *obj;
	lua_State *S;

	uri = luaL_checkstring(T, 1);
	lem_debug("opening %s", uri);

	dbus_error_init(&err);
	conn = dbus_connection_open_private(uri, &err);

	if (dbus_error_is_set(&err)) {
		lua_pushnil(T);
		lua_pushstring(T, err.message);
		dbus_error_free(&err);
		return 2;
	}

	if (conn == NULL) {
		lua_pushnil(T);
		lua_pushliteral(T, "error opening connection");
		return 2;
	}

	dbus_connection_set_exit_on_disconnect(conn, FALSE);

	/* set watch functions */
	if (!dbus_connection_set_watch_functions(conn,
	                                         watch_add,
	                                         watch_remove,
	                                         watch_toggle,
	                                         conn, NULL)) {
		dbus_connection_close(conn);
		dbus_connection_unref(conn);
		lua_pushnil(T);
		lua_pushliteral(T, "error setting watch functions");
		return 2;
	}

	/* set timout functions */
	if (!dbus_connection_set_timeout_functions(conn,
	                                           timeout_add,
	                                           timeout_remove,
	                                           timeout_toggle,
	                                           conn, NULL)) {
		dbus_connection_close(conn);
		dbus_connection_unref(conn);
		lua_pushnil(T);
		lua_pushliteral(T, "error setting timeout functions");
		return 2;
	}

	/* create new userdata for the bus */
	obj = lua_newuserdata(T, sizeof(struct bus_object));
	obj->conn = conn;

	/* set the metatable */
	lua_pushvalue(T, lua_upvalueindex(1));
	lua_setmetatable(T, -2);

	/* create fenv table */
	lua_createtable(T, 2, 0);

	/* create signal handler thread */
	S = lua_newthread(T);
	lua_rawseti(T, -2, 1);

	/* put a reference to bus object and
	 * message metatable on thread */
	lua_pushvalue(T, -2);
	lua_pushvalue(T, lua_upvalueindex(2));
	lua_xmove(T, S, 2);

	/* create signal handler table */
	lua_newtable(S);
	lua_pushvalue(S, -1);
	lua_xmove(S, T, 1);
	lua_rawseti(T, -2, 2);

	/* create object path table */
	lua_newtable(S);
	lua_pushvalue(S, -1);
	lua_xmove(S, T, 1);
	lua_rawseti(T, -2, 3);

	/* set fenv table */
	lua_setfenv(T, -2);

	/* set the message filter */
	if (!dbus_connection_add_filter(conn, message_filter, S, NULL)) {
		dbus_connection_close(conn);
		dbus_connection_unref(conn);
		lua_pushnil(T);
		lua_pushliteral(T, "out of memory");
		return 2;
	}

	/* return the bus object */
	return 1;
}
static void*
with_bus_thread_func (void *data)
{
  DBusError error;
  DBusConnection *connection;
  ClientData cd;
  const char *address;
  GMainContext *context;
  
  g_printerr ("Starting client thread %p\n", g_thread_self());  

  address = g_getenv ("DBUS_SESSION_BUS_ADDRESS");
  if (address == NULL)
    {
      g_printerr ("DBUS_SESSION_BUS_ADDRESS not set\n");
      exit (1);
    }
  
  dbus_error_init (&error);
  connection = dbus_connection_open_private (address, &error);
  if (connection == NULL)
    {
      g_printerr ("could not open connection to bus: %s\n", error.message);
      dbus_error_free (&error);
      exit (1);
    }

  if (!dbus_bus_register (connection, &error))
    {
      g_printerr ("could not register with bus: %s\n", error.message);
      dbus_error_free (&error);
      exit (1);
    }
  
  context = g_main_context_new ();

  cd.iterations = 1;
  cd.loop = g_main_loop_new (context, FALSE);
  
  if (!dbus_connection_add_filter (connection,
				   with_bus_client_filter, &cd, NULL))
    g_error ("no memory");
  
  dbus_connection_setup_with_g_main (connection, context);

  g_printerr ("Client thread sending message to prime pingpong\n");
  send_echo_method_call (connection);
  g_printerr ("Client thread sent message\n");

  g_printerr ("Client thread entering main loop\n");
  g_main_loop_run (cd.loop);
  g_printerr ("Client thread %p exiting main loop\n",
              g_thread_self());

  dbus_connection_close (connection);
  
  g_main_loop_unref (cd.loop);
  g_main_context_unref (context);
  
  return NULL;
}