Ejemplo n.º 1
0
void
test_expand (void)
{
	NihError *error;
	char     *env[7], *str;

	TEST_FUNCTION ("environ_expand");
	env[0] = "FOO=frodo";
	env[1] = "BAR=bilbo";
	env[2] = "BAZ=xx";
	env[3] = "HOBBIT=FOO";
	env[4] = "NULL=";
	env[5] = "DOH=oops";
	env[6] = NULL;

	nih_error_push_context();
	nih_error_pop_context ();


	/* Check that we can expand a string containing no expansion.
	 */
	TEST_FEATURE ("with no expansion");
	TEST_ALLOC_FAIL {
		str = environ_expand (NULL, "this is a test", env);

		if (test_alloc_failed) {
			TEST_EQ_P (str, NULL);

			error = nih_error_get ();
			TEST_EQ (error->number, ENOMEM);
			nih_free (error);
			continue;
		}

		TEST_EQ_STR (str, "this is a test");

		nih_free (str);
	}


	/* Check that we can expand a simple string containing a reference
	 * from the environment, with the reference replaced by the environment
	 * variable value.
	 */
	TEST_FEATURE ("with simple expansion");
	TEST_ALLOC_FAIL {
		str = environ_expand (NULL, "this is a $FOO test", env);

		if (test_alloc_failed) {
			TEST_EQ_P (str, NULL);

			error = nih_error_get ();
			TEST_EQ (error->number, ENOMEM);
			nih_free (error);
			continue;
		}

		TEST_EQ_STR (str, "this is a frodo test");

		nih_free (str);
	}


	/* Check that we can expand a simple string containing a reference
	 * from the environment that is smaller than the reference, with the
	 * reference replaced by the environment variable value.
	 */
	TEST_FEATURE ("with simple expansion of smaller value");
	TEST_ALLOC_FAIL {
		str = environ_expand (NULL, "this is a $BAZ test", env);

		if (test_alloc_failed) {
			TEST_EQ_P (str, NULL);

			error = nih_error_get ();
			TEST_EQ (error->number, ENOMEM);
			nih_free (error);
			continue;
		}

		TEST_EQ_STR (str, "this is a xx test");

		nih_free (str);
	}


	/* Check that we can expand a simple string containing a reference
	 * from the environment that is exactly the same size as the
	 * reference, with the reference replaced by the environment variable
	 * value.
	 */
	TEST_FEATURE ("with simple expansion of same size value");
	TEST_ALLOC_FAIL {
		str = environ_expand (NULL, "this is a $DOH test", env);

		if (test_alloc_failed) {
			TEST_EQ_P (str, NULL);

			error = nih_error_get ();
			TEST_EQ (error->number, ENOMEM);
			nih_free (error);
			continue;
		}

		TEST_EQ_STR (str, "this is a oops test");

		nih_free (str);
	}


	/* Check that we can expand a string containing multiple simple
	 * references, with each replaced by the variable value.
	 */
	TEST_FEATURE ("with multiple simple expansions");
	TEST_ALLOC_FAIL {
		str = environ_expand (NULL, "test $FOO $BAR$BAZ", env);

		if (test_alloc_failed) {
			TEST_EQ_P (str, NULL);

			error = nih_error_get ();
			TEST_EQ (error->number, ENOMEM);
			nih_free (error);
			continue;
		}

		TEST_EQ_STR (str, "test frodo bilboxx");

		nih_free (str);
	}


	/* Check that we can expand a string containing a bracketed
	 * reference, allowing it to nestle against other alphanumerics.
	 */
	TEST_FEATURE ("with simple bracketed expression");
	TEST_ALLOC_FAIL {
		str = environ_expand (NULL, "${BAR}test", env);

		if (test_alloc_failed) {
			TEST_EQ_P (str, NULL);

			error = nih_error_get ();
			TEST_EQ (error->number, ENOMEM);
			nih_free (error);
			continue;
		}

		TEST_EQ_STR (str, "bilbotest");

		nih_free (str);
	}


	/* Check that we can expand a string containing multiple bracketed
	 * references, allowing it to nestle against other alphanumerics.
	 */
	TEST_FEATURE ("with multiple simple bracketed expression");
	TEST_ALLOC_FAIL {
		str = environ_expand (NULL, "${BAR}${FOO}test${BAZ}", env);

		if (test_alloc_failed) {
			TEST_EQ_P (str, NULL);

			error = nih_error_get ();
			TEST_EQ (error->number, ENOMEM);
			nih_free (error);
			continue;
		}

		TEST_EQ_STR (str, "bilbofrodotestxx");

		nih_free (str);
	}


	/* Check that simple expressions may appear within bracketed
	 * expressions, causing them to be evaluted and the evalution
	 * serving as the reference.
	 */
	TEST_FEATURE ("with simple expression inside bracketed expression");
	TEST_ALLOC_FAIL {
		str = environ_expand (NULL, "${$HOBBIT} baggins", env);

		if (test_alloc_failed) {
			TEST_EQ_P (str, NULL);

			error = nih_error_get ();
			TEST_EQ (error->number, ENOMEM);
			nih_free (error);
			continue;
		}

		TEST_EQ_STR (str, "frodo baggins");

		nih_free (str);
	}


	/* Check that bracketed expressions may appear within bracketed
	 * expressions.
	 */
	TEST_FEATURE ("with bracketed expression inside bracketed expression");
	TEST_ALLOC_FAIL {
		str = environ_expand (NULL, "${${HOBBIT}} baggins", env);

		if (test_alloc_failed) {
			TEST_EQ_P (str, NULL);

			error = nih_error_get ();
			TEST_EQ (error->number, ENOMEM);
			nih_free (error);
			continue;
		}

		TEST_EQ_STR (str, "frodo baggins");

		nih_free (str);
	}


	/* Check that we can substitute a default value if the variable
	 * we were after was unset.
	 */
	TEST_FEATURE ("with bracketed default expression");
	TEST_ALLOC_FAIL {
		str = environ_expand (NULL, "${MEEP-a }test", env);

		if (test_alloc_failed) {
			TEST_EQ_P (str, NULL);

			error = nih_error_get ();
			TEST_EQ (error->number, ENOMEM);
			nih_free (error);
			continue;
		}

		TEST_EQ_STR (str, "a test");

		nih_free (str);
	}


	/* Check that a default expression uses the environment value if
	 * it is actually set.
	 */
	TEST_FEATURE ("with bracketed default expression for set variable");
	TEST_ALLOC_FAIL {
		str = environ_expand (NULL, "${BAZ-a }test", env);

		if (test_alloc_failed) {
			TEST_EQ_P (str, NULL);

			error = nih_error_get ();
			TEST_EQ (error->number, ENOMEM);
			nih_free (error);
			continue;
		}

		TEST_EQ_STR (str, "xxtest");

		nih_free (str);
	}


	/* Check that a default expression uses the environment value if
	 * it is actually set, even if it is NULL.
	 */
	TEST_FEATURE ("with bracketed default expression for null variable");
	TEST_ALLOC_FAIL {
		str = environ_expand (NULL, "${NULL-a }test", env);

		if (test_alloc_failed) {
			TEST_EQ_P (str, NULL);

			error = nih_error_get ();
			TEST_EQ (error->number, ENOMEM);
			nih_free (error);
			continue;
		}

		TEST_EQ_STR (str, "test");

		nih_free (str);
	}


	/* Check that we can substitute a default value if the variable
	 * we were after was unset (or null).
	 */
	TEST_FEATURE ("with bracketed default or null expression");
	TEST_ALLOC_FAIL {
		str = environ_expand (NULL, "${MEEP:-a }test", env);

		if (test_alloc_failed) {
			TEST_EQ_P (str, NULL);

			error = nih_error_get ();
			TEST_EQ (error->number, ENOMEM);
			nih_free (error);
			continue;
		}

		TEST_EQ_STR (str, "a test");

		nih_free (str);
	}


	/* Check that a default or null expression uses the environment value
	 * if it is actually set and not null.
	 */
	TEST_FEATURE ("with bracketed default or null expression for set variable");
	TEST_ALLOC_FAIL {
		str = environ_expand (NULL, "${BAZ:-a }test", env);

		if (test_alloc_failed) {
			TEST_EQ_P (str, NULL);

			error = nih_error_get ();
			TEST_EQ (error->number, ENOMEM);
			nih_free (error);
			continue;
		}

		TEST_EQ_STR (str, "xxtest");

		nih_free (str);
	}


	/* Check that we can substitute a default value if the variable
	 * we were after was null.
	 */
	TEST_FEATURE ("with bracketed default or null expression for null variable");
	TEST_ALLOC_FAIL {
		str = environ_expand (NULL, "${NULL:-a }test", env);

		if (test_alloc_failed) {
			TEST_EQ_P (str, NULL);

			error = nih_error_get ();
			TEST_EQ (error->number, ENOMEM);
			nih_free (error);
			continue;
		}

		TEST_EQ_STR (str, "a test");

		nih_free (str);
	}


	/* Check that we don't substitute an alternate value if the
	 * variable we were after was unset.
	 */
	TEST_FEATURE ("with bracketed alternate expression");
	TEST_ALLOC_FAIL {
		str = environ_expand (NULL, "${MEEP+good }test", env);

		if (test_alloc_failed) {
			TEST_EQ_P (str, NULL);

			error = nih_error_get ();
			TEST_EQ (error->number, ENOMEM);
			nih_free (error);
			continue;
		}

		TEST_EQ_STR (str, "test");

		nih_free (str);
	}


	/* Check that we use the alternate value if the environment variable
	 * is actually set.
	 */
	TEST_FEATURE ("with bracketed alternate expression for set variable");
	TEST_ALLOC_FAIL {
		str = environ_expand (NULL, "${BAZ+good }test", env);

		if (test_alloc_failed) {
			TEST_EQ_P (str, NULL);

			error = nih_error_get ();
			TEST_EQ (error->number, ENOMEM);
			nih_free (error);
			continue;
		}

		TEST_EQ_STR (str, "good test");

		nih_free (str);
	}


	/* Check that we use the alternate value if the environment variable
	 * is set, even if it is NULL.
	 */
	TEST_FEATURE ("with bracketed alternate expression for null variable");
	TEST_ALLOC_FAIL {
		str = environ_expand (NULL, "${NULL+good }test", env);

		if (test_alloc_failed) {
			TEST_EQ_P (str, NULL);

			error = nih_error_get ();
			TEST_EQ (error->number, ENOMEM);
			nih_free (error);
			continue;
		}

		TEST_EQ_STR (str, "good test");

		nih_free (str);
	}


	/* Check that we don't substitute an alternate value if the
	 * variable we were after was unset (or null).
	 */
	TEST_FEATURE ("with bracketed alternate or null expression");
	TEST_ALLOC_FAIL {
		str = environ_expand (NULL, "${MEEP:+good }test", env);

		if (test_alloc_failed) {
			TEST_EQ_P (str, NULL);

			error = nih_error_get ();
			TEST_EQ (error->number, ENOMEM);
			nih_free (error);
			continue;
		}

		TEST_EQ_STR (str, "test");

		nih_free (str);
	}


	/* Check that we use the alternate value if the environment variable
	 * is actually set and not null.
	 */
	TEST_FEATURE ("with bracketed alternate or null expression for set variable");
	TEST_ALLOC_FAIL {
		str = environ_expand (NULL, "${BAZ:+good }test", env);

		if (test_alloc_failed) {
			TEST_EQ_P (str, NULL);

			error = nih_error_get ();
			TEST_EQ (error->number, ENOMEM);
			nih_free (error);
			continue;
		}

		TEST_EQ_STR (str, "good test");

		nih_free (str);
	}


	/* Check that we don't substitute an alternate value if the
	 * variable we were after was set, but was null.
	 */
	TEST_FEATURE ("with bracketed alternate or null expression for null variable");
	TEST_ALLOC_FAIL {
		str = environ_expand (NULL, "${NULL:+good }test", env);

		if (test_alloc_failed) {
			TEST_EQ_P (str, NULL);

			error = nih_error_get ();
			TEST_EQ (error->number, ENOMEM);
			nih_free (error);
			continue;
		}

		TEST_EQ_STR (str, "test");

		nih_free (str);
	}


	/* Check that references on either side of an expression are
	 * expanded before evaluation.
	 */
	TEST_FEATURE ("with references in bracketed expression argument");
	TEST_ALLOC_FAIL {
		str = environ_expand (NULL, "${$BAZ:-${$HOBBIT}}test", env);

		if (test_alloc_failed) {
			TEST_EQ_P (str, NULL);

			error = nih_error_get ();
			TEST_EQ (error->number, ENOMEM);
			nih_free (error);
			continue;
		}

		TEST_EQ_STR (str, "frodotest");

		nih_free (str);
	}


	/* Check that a literal dollar sign with no following text is
	 * treated just as a dollar sign.
	 */
	TEST_FEATURE ("with dollar sign in whitespace");
	TEST_ALLOC_FAIL {
		str = environ_expand (NULL, "this is a $ test", env);

		if (test_alloc_failed) {
			TEST_EQ_P (str, NULL);

			error = nih_error_get ();
			TEST_EQ (error->number, ENOMEM);
			nih_free (error);
			continue;
		}

		TEST_EQ_STR (str, "this is a $ test");

		nih_free (str);
	}


	/* Check that a literal dollar sign in text can be followed by empty
	 * brackets to be just as a dollar sign.
	 */
	TEST_FEATURE ("with bracketed dollar sign");
	TEST_ALLOC_FAIL {
		str = environ_expand (NULL, "${}test", env);

		if (test_alloc_failed) {
			TEST_EQ_P (str, NULL);

			error = nih_error_get ();
			TEST_EQ (error->number, ENOMEM);
			nih_free (error);
			continue;
		}

		TEST_EQ_STR (str, "$test");

		nih_free (str);
	}


	/* Check that attempting to expand an unknown variable results in
	 * an error being raised.
	 */
	TEST_FEATURE ("with simple expansion of unknown variable");
	str = environ_expand (NULL, "this is a $WIBBLE test", env);

	TEST_EQ_P (str, NULL);

	error = nih_error_get ();
	TEST_EQ (error->number, ENVIRON_UNKNOWN_PARAM);
	nih_free (error);


	/* Check that attempting to expand an unknown variable results in
	 * an error being raised.
	 */
	TEST_FEATURE ("with bracketed expansion of unknown variable");
	str = environ_expand (NULL, "this is a ${WIBBLE} test", env);

	TEST_EQ_P (str, NULL);

	error = nih_error_get ();
	TEST_EQ (error->number, ENVIRON_UNKNOWN_PARAM);
	nih_free (error);


	/* Check that attempting to expand an unknown variable results in
	 * an error being raised.
	 */
	TEST_FEATURE ("with expansion of unknown variable within expression name");
	str = environ_expand (NULL, "this is a ${$WIBBLE:-$FOO} test", env);

	TEST_EQ_P (str, NULL);

	error = nih_error_get ();
	TEST_EQ (error->number, ENVIRON_UNKNOWN_PARAM);
	nih_free (error);


	/* Check that attempting to expand an unknown variable results in
	 * an error being raised.
	 */
	TEST_FEATURE ("with expansion of unknown variable within expression argument");
	str = environ_expand (NULL, "this is a ${$FOO:-$WIBBLE} test", env);

	TEST_EQ_P (str, NULL);

	error = nih_error_get ();
	TEST_EQ (error->number, ENVIRON_UNKNOWN_PARAM);
	nih_free (error);


	/* Check that inventing a new operator results in an error
	 * being raised.
	 */
	TEST_FEATURE ("with unknown operator in expression");
	str = environ_expand (NULL, "this is a ${$FOO:!$BAR test", env);

	TEST_EQ_P (str, NULL);

	error = nih_error_get ();
	TEST_EQ (error->number, ENVIRON_EXPECTED_OPERATOR);
	nih_free (error);


	/* Check that forgetting to close a brace results in an error
	 * being raised.
	 */
	TEST_FEATURE ("with missing close brace after expression");
	str = environ_expand (NULL, "this is a ${$FOO:-$BAR test", env);

	TEST_EQ_P (str, NULL);

	error = nih_error_get ();
	TEST_EQ (error->number, ENVIRON_MISMATCHED_BRACES);
	nih_free (error);
}
DBusHandlerResult
my_com_netsplit_Nih_Test_Method_method (NihDBusObject * object,
                                        NihDBusMessage *message)
{
	DBusMessageIter    iter;
	DBusMessage *      reply;
	MyMethodStructure *structure;
	DBusMessageIter    structure_iter;
	const char *       structure_item0;
	uint32_t           structure_item1;

	nih_assert (object != NULL);
	nih_assert (message != NULL);

	/* Iterate the arguments to the message and demarshal into arguments
	 * for our own function call.
	 */
	dbus_message_iter_init (message->message, &iter);

	if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
		reply = dbus_message_new_error (message->message, DBUS_ERROR_INVALID_ARGS,
		                                "Invalid arguments to Method method");
		if (! reply)
			return DBUS_HANDLER_RESULT_NEED_MEMORY;

		if (! dbus_connection_send (message->connection, reply, NULL)) {
			dbus_message_unref (reply);
			return DBUS_HANDLER_RESULT_NEED_MEMORY;
		}

		dbus_message_unref (reply);
		return DBUS_HANDLER_RESULT_HANDLED;
	}

	/* Call the handler function */
	nih_error_push_context ();
	if (my_method (object->data, message, &structure) < 0) {
		NihError *err;

		err = nih_error_get ();
		if (err->number == ENOMEM) {
			nih_free (err);
			nih_error_pop_context ();

			return DBUS_HANDLER_RESULT_NEED_MEMORY;
		} else if (err->number == NIH_DBUS_ERROR) {
			NihDBusError *dbus_err = (NihDBusError *)err;

			reply = NIH_MUST (dbus_message_new_error (message->message, dbus_err->name, err->message));
			nih_free (err);
			nih_error_pop_context ();

			NIH_MUST (dbus_connection_send (message->connection, reply, NULL));

			dbus_message_unref (reply);
			return DBUS_HANDLER_RESULT_HANDLED;
		} else {
			reply = NIH_MUST (dbus_message_new_error (message->message, DBUS_ERROR_FAILED, err->message));
			nih_free (err);
			nih_error_pop_context ();

			NIH_MUST (dbus_connection_send (message->connection, reply, NULL));

			dbus_message_unref (reply);
			return DBUS_HANDLER_RESULT_HANDLED;
		}
	}
	nih_error_pop_context ();

	/* If the sender doesn't care about a reply, don't bother wasting
	 * effort constructing and sending one.
	 */
	if (dbus_message_get_no_reply (message->message))
		return DBUS_HANDLER_RESULT_HANDLED;

	do {
		__label__ enomem;

		/* Construct the reply message. */
		reply = dbus_message_new_method_return (message->message);
		if (! reply)
			goto enomem;

		dbus_message_iter_init_append (reply, &iter);

		/* Marshal a structure onto the message */
		if (! dbus_message_iter_open_container (&iter, DBUS_TYPE_STRUCT, NULL, &structure_iter)) {
			dbus_message_unref (reply);
			reply = NULL;
			goto enomem;
		}

		structure_item0 = structure->item0;

		/* Marshal a char * onto the message */
		if (! dbus_message_iter_append_basic (&structure_iter, DBUS_TYPE_STRING, &structure_item0)) {
			dbus_message_iter_abandon_container (&iter, &structure_iter);
			dbus_message_unref (reply);
			reply = NULL;
			goto enomem;
		}

		structure_item1 = structure->item1;

		/* Marshal a uint32_t onto the message */
		if (! dbus_message_iter_append_basic (&structure_iter, DBUS_TYPE_UINT32, &structure_item1)) {
			dbus_message_iter_abandon_container (&iter, &structure_iter);
			dbus_message_unref (reply);
			reply = NULL;
			goto enomem;
		}

		if (! dbus_message_iter_close_container (&iter, &structure_iter)) {
			dbus_message_unref (reply);
			reply = NULL;
			goto enomem;
		}
	enomem: __attribute__ ((unused));
	} while (! reply);

	/* Send the reply, appending it to the outgoing queue. */
	NIH_MUST (dbus_connection_send (message->connection, reply, NULL));

	dbus_message_unref (reply);

	return DBUS_HANDLER_RESULT_HANDLED;
}
static DBusHandlerResult
my_com_netsplit_Nih_Foo_Bing_method (NihDBusObject * object,
                                     NihDBusMessage *message)
{
	DBusMessageIter iter;
	DBusMessage *   reply;

	nih_assert (object != NULL);
	nih_assert (message != NULL);

	/* Iterate the arguments to the message and demarshal into arguments
	 * for our own function call.
	 */
	dbus_message_iter_init (message->message, &iter);

	if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
		reply = dbus_message_new_error (message->message, DBUS_ERROR_INVALID_ARGS,
		                                "Invalid arguments to Bing method");
		if (! reply)
			return DBUS_HANDLER_RESULT_NEED_MEMORY;

		if (! dbus_connection_send (message->connection, reply, NULL)) {
			dbus_message_unref (reply);
			return DBUS_HANDLER_RESULT_NEED_MEMORY;
		}

		dbus_message_unref (reply);
		return DBUS_HANDLER_RESULT_HANDLED;
	}

	/* Call the handler function */
	nih_error_push_context ();
	if (my_foo_bing (object->data, message) < 0) {
		NihError *err;

		err = nih_error_get ();
		if (err->number == ENOMEM) {
			nih_free (err);
			nih_error_pop_context ();

			return DBUS_HANDLER_RESULT_NEED_MEMORY;
		} else if (err->number == NIH_DBUS_ERROR) {
			NihDBusError *dbus_err = (NihDBusError *)err;

			reply = NIH_MUST (dbus_message_new_error (message->message, dbus_err->name, err->message));
			nih_free (err);
			nih_error_pop_context ();

			NIH_MUST (dbus_connection_send (message->connection, reply, NULL));

			dbus_message_unref (reply);
			return DBUS_HANDLER_RESULT_HANDLED;
		} else {
			reply = NIH_MUST (dbus_message_new_error (message->message, DBUS_ERROR_FAILED, err->message));
			nih_free (err);
			nih_error_pop_context ();

			NIH_MUST (dbus_connection_send (message->connection, reply, NULL));

			dbus_message_unref (reply);
			return DBUS_HANDLER_RESULT_HANDLED;
		}
	}
	nih_error_pop_context ();

	/* If the sender doesn't care about a reply, don't bother wasting
	 * effort constructing and sending one.
	 */
	if (dbus_message_get_no_reply (message->message))
		return DBUS_HANDLER_RESULT_HANDLED;

	do {
		__label__ enomem;

		/* Construct the reply message. */
		reply = dbus_message_new_method_return (message->message);
		if (! reply)
			goto enomem;

		dbus_message_iter_init_append (reply, &iter);
	enomem: __attribute__ ((unused));
	} while (! reply);

	/* Send the reply, appending it to the outgoing queue. */
	NIH_MUST (dbus_connection_send (message->connection, reply, NULL));

	dbus_message_unref (reply);

	return DBUS_HANDLER_RESULT_HANDLED;
}
static DBusHandlerResult
my_com_netsplit_Nih_Test_Peek_method (NihDBusObject * object,
                                      NihDBusMessage *message)
{
	DBusMessageIter iter;
	DBusMessage *   reply;
	uint32_t        address;

	nih_assert (object != NULL);
	nih_assert (message != NULL);

	/* Iterate the arguments to the message and demarshal into arguments
	 * for our own function call.
	 */
	dbus_message_iter_init (message->message, &iter);

	/* Demarshal a uint32_t from the message */
	if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32) {
		reply = dbus_message_new_error (message->message, DBUS_ERROR_INVALID_ARGS,
		                                "Invalid arguments to Peek method");
		if (! reply)
			return DBUS_HANDLER_RESULT_NEED_MEMORY;

		if (! dbus_connection_send (message->connection, reply, NULL)) {
			dbus_message_unref (reply);
			return DBUS_HANDLER_RESULT_NEED_MEMORY;
		}

		dbus_message_unref (reply);
		return DBUS_HANDLER_RESULT_HANDLED;
	}

	dbus_message_iter_get_basic (&iter, &address);

	dbus_message_iter_next (&iter);

	if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
		reply = dbus_message_new_error (message->message, DBUS_ERROR_INVALID_ARGS,
		                                "Invalid arguments to Peek method");
		if (! reply)
			return DBUS_HANDLER_RESULT_NEED_MEMORY;

		if (! dbus_connection_send (message->connection, reply, NULL)) {
			dbus_message_unref (reply);
			return DBUS_HANDLER_RESULT_NEED_MEMORY;
		}

		dbus_message_unref (reply);
		return DBUS_HANDLER_RESULT_HANDLED;
	}

	/* Call the handler function */
	nih_error_push_context ();
	if (my_test_peek (object->data, message, address) < 0) {
		NihError *err;

		err = nih_error_get ();
		if (err->number == ENOMEM) {
			nih_free (err);
			nih_error_pop_context ();

			return DBUS_HANDLER_RESULT_NEED_MEMORY;
		} else if (err->number == NIH_DBUS_ERROR) {
			NihDBusError *dbus_err = (NihDBusError *)err;

			reply = NIH_MUST (dbus_message_new_error (message->message, dbus_err->name, err->message));
			nih_free (err);
			nih_error_pop_context ();

			NIH_MUST (dbus_connection_send (message->connection, reply, NULL));

			dbus_message_unref (reply);
			return DBUS_HANDLER_RESULT_HANDLED;
		} else {
			reply = NIH_MUST (dbus_message_new_error (message->message, DBUS_ERROR_FAILED, err->message));
			nih_free (err);
			nih_error_pop_context ();

			NIH_MUST (dbus_connection_send (message->connection, reply, NULL));

			dbus_message_unref (reply);
			return DBUS_HANDLER_RESULT_HANDLED;
		}
	}
	nih_error_pop_context ();

	return DBUS_HANDLER_RESULT_HANDLED;
}
void
my_com_netsplit_Nih_Test_property_get_notify (DBusPendingCall *   pending_call,
                                              NihDBusPendingData *pending_data)
{
	DBusMessage *   reply;
	DBusMessageIter iter;
	DBusMessageIter variter;
	NihDBusMessage *message;
	DBusError       error;
	const char *    value_dbus;
	char *          value;

	nih_assert (pending_call != NULL);
	nih_assert (pending_data != NULL);

	nih_assert (dbus_pending_call_get_completed (pending_call));

	/* Steal the reply from the pending call. */
	reply = dbus_pending_call_steal_reply (pending_call);
	nih_assert (reply != NULL);

	/* Handle error replies */
	if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR) {
		message = NIH_MUST (nih_dbus_message_new (pending_data, pending_data->connection, reply));

		dbus_error_init (&error);
		dbus_set_error_from_message (&error, message->message);

		nih_error_push_context ();
		nih_dbus_error_raise (error.name, error.message);
		pending_data->error_handler (pending_data->data, message);
		nih_error_pop_context ();

		dbus_error_free (&error);
		nih_free (message);
		dbus_message_unref (reply);
		return;
	}

	nih_assert (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_METHOD_RETURN);

	do {
		__label__ enomem;

		/* Create a message context for the reply, and iterate
		 * over and recurse into the arguments.
		 */
		message = nih_dbus_message_new (pending_data, pending_data->connection, reply);
		if (! message)
			goto enomem;

		dbus_message_iter_init (message->message, &iter);

		if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_VARIANT) {
			nih_error_push_context ();
			nih_error_raise (NIH_DBUS_INVALID_ARGS,
			                 _(NIH_DBUS_INVALID_ARGS_STR));
			pending_data->error_handler (pending_data->data, message);
			nih_error_pop_context ();

			nih_free (message);
			dbus_message_unref (reply);
			return;
		}

		dbus_message_iter_recurse (&iter, &variter);

		/* Demarshal a char * from the message */
		if (dbus_message_iter_get_arg_type (&variter) != DBUS_TYPE_STRING) {
			nih_error_push_context ();
			nih_error_raise (NIH_DBUS_INVALID_ARGS,
			                 _(NIH_DBUS_INVALID_ARGS_STR));
			pending_data->error_handler (pending_data->data, message);
			nih_error_pop_context ();

			nih_free (message);
			dbus_message_unref (reply);
			return;
		}

		dbus_message_iter_get_basic (&variter, &value_dbus);

		value = nih_strdup (message, value_dbus);
		if (! value) {
			nih_free (message);
			message = NULL;
			goto enomem;
		}

		dbus_message_iter_next (&variter);

		dbus_message_iter_next (&iter);

		if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
			nih_error_push_context ();
			nih_error_raise (NIH_DBUS_INVALID_ARGS,
			                 _(NIH_DBUS_INVALID_ARGS_STR));
			pending_data->error_handler (pending_data->data, message);
			nih_error_pop_context ();

			nih_free (message);
			dbus_message_unref (reply);
			return;
		}

	enomem: __attribute__ ((unused));
	} while (! message);

	/* Call the handler function */
	nih_error_push_context ();
	((MyGetPropertyReply)pending_data->handler) (pending_data->data, message, value);
	nih_error_pop_context ();

	nih_free (message);
	dbus_message_unref (reply);
}
void
my_com_netsplit_Nih_Test_get_all_notify (DBusPendingCall *   pending_call,
                                         NihDBusPendingData *pending_data)
{
	DBusMessage *   reply;
	DBusMessageIter iter;
	DBusMessageIter arrayiter;
	DBusMessageIter dictiter;
	DBusMessageIter variter;
	NihDBusMessage *message;
	DBusError       error;
	const char *    property;
	MyProperties *  properties;
	size_t          property_count;
	char *          name;
	const char *    name_dbus;
	uint32_t        size;

	nih_assert (pending_call != NULL);
	nih_assert (pending_data != NULL);

	nih_assert (dbus_pending_call_get_completed (pending_call));

	/* Steal the reply from the pending call. */
	reply = dbus_pending_call_steal_reply (pending_call);
	nih_assert (reply != NULL);

	/* Handle error replies */
	if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR) {
		message = NIH_MUST (nih_dbus_message_new (pending_data, pending_data->connection, reply));

		dbus_error_init (&error);
		dbus_set_error_from_message (&error, message->message);

		nih_error_push_context ();
		nih_dbus_error_raise (error.name, error.message);
		pending_data->error_handler (pending_data->data, message);
		nih_error_pop_context ();

		dbus_error_free (&error);
		nih_free (message);
		dbus_message_unref (reply);
		return;
	}

	nih_assert (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_METHOD_RETURN);

	/* Create a message context for the reply, and iterate
	 * over and recurse into the arguments.
	 */
	message = NIH_MUST (nih_dbus_message_new (pending_data, pending_data->connection, reply));

	/* Iterate the method arguments, recursing into the array */
	dbus_message_iter_init (reply, &iter);

	if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY) {
		nih_error_push_context ();
		nih_error_raise (NIH_DBUS_INVALID_ARGS,
		                 _(NIH_DBUS_INVALID_ARGS_STR));
		pending_data->error_handler (pending_data->data, message);
		nih_error_pop_context ();

		nih_free (message);
		dbus_message_unref (reply);
		return;
	}

	properties = NIH_MUST (nih_new (message, MyProperties));
	property_count = 0;

	dbus_message_iter_recurse (&iter, &arrayiter);

	while (dbus_message_iter_get_arg_type (&arrayiter) != DBUS_TYPE_INVALID) {
		__label__ enomem;

		if (dbus_message_iter_get_arg_type (&arrayiter) != DBUS_TYPE_DICT_ENTRY) {
			nih_error_push_context ();
			nih_error_raise (NIH_DBUS_INVALID_ARGS,
			                 _(NIH_DBUS_INVALID_ARGS_STR));
			pending_data->error_handler (pending_data->data, message);
			nih_error_pop_context ();

			nih_free (message);
			dbus_message_unref (reply);
			return;
		}

		dbus_message_iter_recurse (&arrayiter, &dictiter);

		if (dbus_message_iter_get_arg_type (&dictiter) != DBUS_TYPE_STRING) {
			nih_error_push_context ();
			nih_error_raise (NIH_DBUS_INVALID_ARGS,
			                 _(NIH_DBUS_INVALID_ARGS_STR));
			pending_data->error_handler (pending_data->data, message);
			nih_error_pop_context ();

			nih_free (message);
			dbus_message_unref (reply);
			return;
		}

		dbus_message_iter_get_basic (&dictiter, &property);

		dbus_message_iter_next (&dictiter);

		if (dbus_message_iter_get_arg_type (&dictiter) != DBUS_TYPE_VARIANT) {
			nih_error_push_context ();
			nih_error_raise (NIH_DBUS_INVALID_ARGS,
			                 _(NIH_DBUS_INVALID_ARGS_STR));
			pending_data->error_handler (pending_data->data, message);
			nih_error_pop_context ();

			nih_free (message);
			dbus_message_unref (reply);
			return;
		}

		dbus_message_iter_recurse (&dictiter, &variter);

		if (! strcmp (property, "name")) {
			/* Demarshal a char * from the message */
			if (dbus_message_iter_get_arg_type (&variter) != DBUS_TYPE_STRING) {
				nih_error_push_context ();
				nih_error_raise (NIH_DBUS_INVALID_ARGS,
				                 _(NIH_DBUS_INVALID_ARGS_STR));
				pending_data->error_handler (pending_data->data, message);
				nih_error_pop_context ();

				nih_free (message);
				dbus_message_unref (reply);
				return;
			}

			dbus_message_iter_get_basic (&variter, &name_dbus);

			name = nih_strdup (properties, name_dbus);
			if (! name) {
				goto enomem;
			}

			dbus_message_iter_next (&variter);

			properties->name = name;

			nih_assert (++property_count);
		}

		if (! strcmp (property, "size")) {
			/* Demarshal a uint32_t from the message */
			if (dbus_message_iter_get_arg_type (&variter) != DBUS_TYPE_UINT32) {
				nih_error_push_context ();
				nih_error_raise (NIH_DBUS_INVALID_ARGS,
				                 _(NIH_DBUS_INVALID_ARGS_STR));
				pending_data->error_handler (pending_data->data, message);
				nih_error_pop_context ();

				nih_free (message);
				dbus_message_unref (reply);
				return;
			}

			dbus_message_iter_get_basic (&variter, &size);

			dbus_message_iter_next (&variter);

			properties->size = size;

			nih_assert (++property_count);
		}

		dbus_message_iter_next (&dictiter);

		if (dbus_message_iter_get_arg_type (&dictiter) != DBUS_TYPE_INVALID) {
			nih_error_push_context ();
			nih_error_raise (NIH_DBUS_INVALID_ARGS,
			                 _(NIH_DBUS_INVALID_ARGS_STR));
			pending_data->error_handler (pending_data->data, message);
			nih_error_pop_context ();

			nih_free (message);
			dbus_message_unref (reply);
			return;
		}

		dbus_message_iter_next (&arrayiter);
	enomem: __attribute__ ((unused));
	}

	dbus_message_iter_next (&iter);

	if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
		nih_error_push_context ();
		nih_error_raise (NIH_DBUS_INVALID_ARGS,
		                 _(NIH_DBUS_INVALID_ARGS_STR));
		pending_data->error_handler (pending_data->data, message);
		nih_error_pop_context ();

		nih_free (message);
		dbus_message_unref (reply);
		return;
	}

	if (property_count < 2) {
		nih_error_push_context ();
		nih_error_raise (NIH_DBUS_INVALID_ARGS,
		                 _(NIH_DBUS_INVALID_ARGS_STR));
		pending_data->error_handler (pending_data->data, message);
		nih_error_pop_context ();

		nih_free (message);
		dbus_message_unref (reply);
		return;
	}

	/* Call the handler function */
	nih_error_push_context ();
	((MyGetAllReply)pending_data->handler) (pending_data->data, message, properties);
	nih_error_pop_context ();

	nih_free (message);
	dbus_message_unref (reply);
}