Home | History | Annotate | Download | only in gdbus
      1 /*
      2  *
      3  *  D-Bus helper library
      4  *
      5  *  Copyright (C) 2004-2011  Marcel Holtmann <marcel (at) holtmann.org>
      6  *
      7  *
      8  *  This program is free software; you can redistribute it and/or modify
      9  *  it under the terms of the GNU General Public License as published by
     10  *  the Free Software Foundation; either version 2 of the License, or
     11  *  (at your option) any later version.
     12  *
     13  *  This program is distributed in the hope that it will be useful,
     14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16  *  GNU General Public License for more details.
     17  *
     18  *  You should have received a copy of the GNU General Public License
     19  *  along with this program; if not, write to the Free Software
     20  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     21  *
     22  */
     23 
     24 #ifdef HAVE_CONFIG_H
     25 #include <config.h>
     26 #endif
     27 
     28 #include <stdio.h>
     29 #include <string.h>
     30 
     31 #include <glib.h>
     32 #include <dbus/dbus.h>
     33 
     34 #include "gdbus.h"
     35 
     36 #define info(fmt...)
     37 #define error(fmt...)
     38 #define debug(fmt...)
     39 
     40 struct generic_data {
     41 	unsigned int refcount;
     42 	GSList *interfaces;
     43 	char *introspect;
     44 };
     45 
     46 struct interface_data {
     47 	char *name;
     48 	const GDBusMethodTable *methods;
     49 	const GDBusSignalTable *signals;
     50 	const GDBusPropertyTable *properties;
     51 	void *user_data;
     52 	GDBusDestroyFunction destroy;
     53 };
     54 
     55 struct security_data {
     56 	GDBusPendingReply pending;
     57 	DBusMessage *message;
     58 	const GDBusMethodTable *method;
     59 	void *iface_user_data;
     60 };
     61 
     62 static void print_arguments(GString *gstr, const char *sig,
     63 						const char *direction)
     64 {
     65 	int i;
     66 
     67 	for (i = 0; sig[i]; i++) {
     68 		char type[32];
     69 		int struct_level, dict_level;
     70 		unsigned int len;
     71 		gboolean complete;
     72 
     73 		complete = FALSE;
     74 		struct_level = dict_level = 0;
     75 		memset(type, 0, sizeof(type));
     76 
     77 		/* Gather enough data to have a single complete type */
     78 		for (len = 0; len < (sizeof(type) - 1) && sig[i]; len++, i++) {
     79 			switch (sig[i]){
     80 			case '(':
     81 				struct_level++;
     82 				break;
     83 			case ')':
     84 				struct_level--;
     85 				if (struct_level <= 0 && dict_level <= 0)
     86 					complete = TRUE;
     87 				break;
     88 			case '{':
     89 				dict_level++;
     90 				break;
     91 			case '}':
     92 				dict_level--;
     93 				if (struct_level <= 0 && dict_level <= 0)
     94 					complete = TRUE;
     95 				break;
     96 			case 'a':
     97 				break;
     98 			default:
     99 				if (struct_level <= 0 && dict_level <= 0)
    100 					complete = TRUE;
    101 				break;
    102 			}
    103 
    104 			type[len] = sig[i];
    105 
    106 			if (complete)
    107 				break;
    108 		}
    109 
    110 
    111 		if (direction)
    112 			g_string_append_printf(gstr,
    113 					"\t\t\t<arg type=\"%s\" direction=\"%s\"/>\n",
    114 					type, direction);
    115 		else
    116 			g_string_append_printf(gstr,
    117 					"\t\t\t<arg type=\"%s\"/>\n",
    118 					type);
    119 	}
    120 }
    121 
    122 static void generate_interface_xml(GString *gstr, struct interface_data *iface)
    123 {
    124 	const GDBusMethodTable *method;
    125 	const GDBusSignalTable *signal;
    126 
    127 	for (method = iface->methods; method && method->name; method++) {
    128 		if (!strlen(method->signature) && !strlen(method->reply))
    129 			g_string_append_printf(gstr, "\t\t<method name=\"%s\"/>\n",
    130 								method->name);
    131 		else {
    132 			g_string_append_printf(gstr, "\t\t<method name=\"%s\">\n",
    133 								method->name);
    134 			print_arguments(gstr, method->signature, "in");
    135 			print_arguments(gstr, method->reply, "out");
    136 			g_string_append_printf(gstr, "\t\t</method>\n");
    137 		}
    138 	}
    139 
    140 	for (signal = iface->signals; signal && signal->name; signal++) {
    141 		if (!strlen(signal->signature))
    142 			g_string_append_printf(gstr, "\t\t<signal name=\"%s\"/>\n",
    143 								signal->name);
    144 		else {
    145 			g_string_append_printf(gstr, "\t\t<signal name=\"%s\">\n",
    146 								signal->name);
    147 			print_arguments(gstr, signal->signature, NULL);
    148 			g_string_append_printf(gstr, "\t\t</signal>\n");
    149 		}
    150 	}
    151 }
    152 
    153 static void generate_introspection_xml(DBusConnection *conn,
    154 				struct generic_data *data, const char *path)
    155 {
    156 	GSList *list;
    157 	GString *gstr;
    158 	char **children;
    159 	int i;
    160 
    161 	g_free(data->introspect);
    162 
    163 	gstr = g_string_new(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE);
    164 
    165 	g_string_append_printf(gstr, "<node>\n");
    166 
    167 	for (list = data->interfaces; list; list = list->next) {
    168 		struct interface_data *iface = list->data;
    169 
    170 		g_string_append_printf(gstr, "\t<interface name=\"%s\">\n",
    171 								iface->name);
    172 
    173 		generate_interface_xml(gstr, iface);
    174 
    175 		g_string_append_printf(gstr, "\t</interface>\n");
    176 	}
    177 
    178 	if (!dbus_connection_list_registered(conn, path, &children))
    179 		goto done;
    180 
    181 	for (i = 0; children[i]; i++)
    182 		g_string_append_printf(gstr, "\t<node name=\"%s\"/>\n",
    183 								children[i]);
    184 
    185 	dbus_free_string_array(children);
    186 
    187 done:
    188 	g_string_append_printf(gstr, "</node>\n");
    189 
    190 	data->introspect = g_string_free(gstr, FALSE);
    191 }
    192 
    193 static DBusMessage *introspect(DBusConnection *connection,
    194 				DBusMessage *message, void *user_data)
    195 {
    196 	struct generic_data *data = user_data;
    197 	DBusMessage *reply;
    198 
    199 	if (!dbus_message_has_signature(message, DBUS_TYPE_INVALID_AS_STRING)) {
    200 		error("Unexpected signature to introspect call");
    201 		return NULL;
    202 	}
    203 
    204 	if (data->introspect == NULL)
    205 		generate_introspection_xml(connection, data,
    206 						dbus_message_get_path(message));
    207 
    208 	reply = dbus_message_new_method_return(message);
    209 	if (reply == NULL)
    210 		return NULL;
    211 
    212 	dbus_message_append_args(reply, DBUS_TYPE_STRING, &data->introspect,
    213 					DBUS_TYPE_INVALID);
    214 
    215 	return reply;
    216 }
    217 
    218 static DBusHandlerResult process_message(DBusConnection *connection,
    219 			DBusMessage *message, const GDBusMethodTable *method,
    220 							void *iface_user_data)
    221 {
    222 	DBusMessage *reply;
    223 
    224 	reply = method->function(connection, message, iface_user_data);
    225 
    226 	if (method->flags & G_DBUS_METHOD_FLAG_NOREPLY) {
    227 		if (reply != NULL)
    228 			dbus_message_unref(reply);
    229 		return DBUS_HANDLER_RESULT_HANDLED;
    230 	}
    231 
    232 	if (method->flags & G_DBUS_METHOD_FLAG_ASYNC) {
    233 		if (reply == NULL)
    234 			return DBUS_HANDLER_RESULT_HANDLED;
    235 	}
    236 
    237 	if (reply == NULL)
    238 		return DBUS_HANDLER_RESULT_NEED_MEMORY;
    239 
    240 	dbus_connection_send(connection, reply, NULL);
    241 	dbus_message_unref(reply);
    242 
    243 	return DBUS_HANDLER_RESULT_HANDLED;
    244 }
    245 
    246 static GDBusPendingReply next_pending = 1;
    247 static GSList *pending_security = NULL;
    248 
    249 static const GDBusSecurityTable *security_table = NULL;
    250 
    251 void g_dbus_pending_success(DBusConnection *connection,
    252 					GDBusPendingReply pending)
    253 {
    254 	GSList *list;
    255 
    256         for (list = pending_security; list; list = list->next) {
    257 		struct security_data *secdata = list->data;
    258 
    259 		if (secdata->pending != pending)
    260 			continue;
    261 
    262 		pending_security = g_slist_remove(pending_security, secdata);
    263 
    264 		process_message(connection, secdata->message,
    265 				secdata->method, secdata->iface_user_data);
    266 
    267 		dbus_message_unref(secdata->message);
    268 		g_free(secdata);
    269 		return;
    270         }
    271 }
    272 
    273 void g_dbus_pending_error_valist(DBusConnection *connection,
    274 				GDBusPendingReply pending, const char *name,
    275 					const char *format, va_list args)
    276 {
    277 	GSList *list;
    278 
    279         for (list = pending_security; list; list = list->next) {
    280 		struct security_data *secdata = list->data;
    281 		DBusMessage *reply;
    282 
    283 		if (secdata->pending != pending)
    284 			continue;
    285 
    286 		pending_security = g_slist_remove(pending_security, secdata);
    287 
    288 		reply = g_dbus_create_error_valist(secdata->message,
    289 							name, format, args);
    290 		if (reply != NULL) {
    291 			dbus_connection_send(connection, reply, NULL);
    292 			dbus_message_unref(reply);
    293 		}
    294 
    295 		dbus_message_unref(secdata->message);
    296 		g_free(secdata);
    297 		return;
    298         }
    299 }
    300 
    301 void g_dbus_pending_error(DBusConnection *connection,
    302 				GDBusPendingReply pending,
    303 				const char *name, const char *format, ...)
    304 {
    305 	va_list args;
    306 
    307 	va_start(args, format);
    308 
    309 	g_dbus_pending_error_valist(connection, pending, name, format, args);
    310 
    311 	va_end(args);
    312 }
    313 
    314 int polkit_check_authorization(DBusConnection *conn,
    315 				const char *action, gboolean interaction,
    316 				void (*function) (dbus_bool_t authorized,
    317 							void *user_data),
    318 						void *user_data, int timeout);
    319 
    320 struct builtin_security_data {
    321 	DBusConnection *conn;
    322 	GDBusPendingReply pending;
    323 };
    324 
    325 static void builtin_security_result(dbus_bool_t authorized, void *user_data)
    326 {
    327 	struct builtin_security_data *data = user_data;
    328 
    329 	if (authorized == TRUE)
    330 		g_dbus_pending_success(data->conn, data->pending);
    331 	else
    332 		g_dbus_pending_error(data->conn, data->pending,
    333 						DBUS_ERROR_AUTH_FAILED, NULL);
    334 
    335 	g_free(data);
    336 }
    337 
    338 static void builtin_security_function(DBusConnection *conn,
    339 						const char *action,
    340 						gboolean interaction,
    341 						GDBusPendingReply pending)
    342 {
    343 	struct builtin_security_data *data;
    344 
    345 	data = g_new0(struct builtin_security_data, 1);
    346 	data->conn = conn;
    347 	data->pending = pending;
    348 
    349 	if (polkit_check_authorization(conn, action, interaction,
    350 				builtin_security_result, data, 30000) < 0)
    351 		g_dbus_pending_error(conn, pending, NULL, NULL);
    352 }
    353 
    354 static gboolean check_privilege(DBusConnection *conn, DBusMessage *msg,
    355 			const GDBusMethodTable *method, void *iface_user_data)
    356 {
    357 	const GDBusSecurityTable *security;
    358 
    359 	for (security = security_table; security && security->privilege;
    360 								security++) {
    361 		struct security_data *secdata;
    362 		gboolean interaction;
    363 
    364 		if (security->privilege != method->privilege)
    365 			continue;
    366 
    367 		secdata = g_new(struct security_data, 1);
    368 		secdata->pending = next_pending++;
    369 		secdata->message = dbus_message_ref(msg);
    370 		secdata->method = method;
    371 		secdata->iface_user_data = iface_user_data;
    372 
    373 		pending_security = g_slist_prepend(pending_security, secdata);
    374 
    375 		if (security->flags & G_DBUS_SECURITY_FLAG_ALLOW_INTERACTION)
    376 			interaction = TRUE;
    377 		else
    378 			interaction = FALSE;
    379 
    380 		if (!(security->flags & G_DBUS_SECURITY_FLAG_BUILTIN) &&
    381 							security->function)
    382 			security->function(conn, security->action,
    383 						interaction, secdata->pending);
    384 		else
    385 			builtin_security_function(conn, security->action,
    386 						interaction, secdata->pending);
    387 
    388 		return TRUE;
    389 	}
    390 
    391 	return FALSE;
    392 }
    393 
    394 static void generic_unregister(DBusConnection *connection, void *user_data)
    395 {
    396 	struct generic_data *data = user_data;
    397 
    398 	g_free(data->introspect);
    399 	g_free(data);
    400 }
    401 
    402 static struct interface_data *find_interface(GSList *interfaces,
    403 						const char *name)
    404 {
    405 	GSList *list;
    406 
    407 	if (name == NULL)
    408 		return NULL;
    409 
    410 	for (list = interfaces; list; list = list->next) {
    411 		struct interface_data *iface = list->data;
    412 		if (!strcmp(name, iface->name))
    413 			return iface;
    414 	}
    415 
    416 	return NULL;
    417 }
    418 
    419 static DBusHandlerResult generic_message(DBusConnection *connection,
    420 					DBusMessage *message, void *user_data)
    421 {
    422 	struct generic_data *data = user_data;
    423 	struct interface_data *iface;
    424 	const GDBusMethodTable *method;
    425 	const char *interface;
    426 
    427 	interface = dbus_message_get_interface(message);
    428 
    429 	iface = find_interface(data->interfaces, interface);
    430 	if (iface == NULL)
    431 		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
    432 
    433 	for (method = iface->methods; method &&
    434 			method->name && method->function; method++) {
    435 		if (dbus_message_is_method_call(message, iface->name,
    436 							method->name) == FALSE)
    437 			continue;
    438 
    439 		if (dbus_message_has_signature(message,
    440 						method->signature) == FALSE)
    441 			continue;
    442 
    443 		if (check_privilege(connection, message, method,
    444 						iface->user_data) == TRUE)
    445 			return DBUS_HANDLER_RESULT_HANDLED;
    446 
    447 		return process_message(connection, message, method,
    448 							iface->user_data);
    449 	}
    450 
    451 	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
    452 }
    453 
    454 static DBusObjectPathVTable generic_table = {
    455 	.unregister_function	= generic_unregister,
    456 	.message_function	= generic_message,
    457 };
    458 
    459 static void invalidate_parent_data(DBusConnection *conn, const char *child_path)
    460 {
    461 	struct generic_data *data = NULL;
    462 	char *parent_path, *slash;
    463 
    464 	parent_path = g_strdup(child_path);
    465 	slash = strrchr(parent_path, '/');
    466 	if (slash == NULL)
    467 		goto done;
    468 
    469 	if (slash == parent_path && parent_path[1] != '\0')
    470 		parent_path[1] = '\0';
    471 	else
    472 		*slash = '\0';
    473 
    474 	if (!strlen(parent_path))
    475 		goto done;
    476 
    477 	if (dbus_connection_get_object_path_data(conn, parent_path,
    478 							(void *) &data) == FALSE) {
    479 		goto done;
    480 	}
    481 
    482 	invalidate_parent_data(conn, parent_path);
    483 
    484 	if (data == NULL)
    485 		goto done;
    486 
    487 	g_free(data->introspect);
    488 	data->introspect = NULL;
    489 
    490 done:
    491 	g_free(parent_path);
    492 }
    493 
    494 static GDBusMethodTable introspect_methods[] = {
    495 	{ "Introspect",	"",	"s", introspect	},
    496 	{ }
    497 };
    498 
    499 static void add_interface(struct generic_data *data, const char *name,
    500 				const GDBusMethodTable *methods,
    501 				const GDBusSignalTable *signals,
    502 				const GDBusPropertyTable *properties,
    503 				void *user_data,
    504 				GDBusDestroyFunction destroy)
    505 {
    506 	struct interface_data *iface;
    507 
    508 	iface = g_new0(struct interface_data, 1);
    509 	iface->name = g_strdup(name);
    510 	iface->methods = methods;
    511 	iface->signals = signals;
    512 	iface->properties = properties;
    513 	iface->user_data = user_data;
    514 	iface->destroy = destroy;
    515 
    516 	data->interfaces = g_slist_append(data->interfaces, iface);
    517 }
    518 
    519 static struct generic_data *object_path_ref(DBusConnection *connection,
    520 							const char *path)
    521 {
    522 	struct generic_data *data;
    523 
    524 	if (dbus_connection_get_object_path_data(connection, path,
    525 						(void *) &data) == TRUE) {
    526 		if (data != NULL) {
    527 			data->refcount++;
    528 			return data;
    529 		}
    530 	}
    531 
    532 	data = g_new0(struct generic_data, 1);
    533 	data->refcount = 1;
    534 
    535 	data->introspect = g_strdup(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE "<node></node>");
    536 
    537 	if (!dbus_connection_register_object_path(connection, path,
    538 						&generic_table, data)) {
    539 		g_free(data->introspect);
    540 		g_free(data);
    541 		return NULL;
    542 	}
    543 
    544 	invalidate_parent_data(connection, path);
    545 
    546 	add_interface(data, DBUS_INTERFACE_INTROSPECTABLE,
    547 			introspect_methods, NULL, NULL, data, NULL);
    548 
    549 	return data;
    550 }
    551 
    552 static gboolean remove_interface(struct generic_data *data, const char *name)
    553 {
    554 	struct interface_data *iface;
    555 
    556 	iface = find_interface(data->interfaces, name);
    557 	if (iface == NULL)
    558 		return FALSE;
    559 
    560 	data->interfaces = g_slist_remove(data->interfaces, iface);
    561 
    562 	if (iface->destroy)
    563 		iface->destroy(iface->user_data);
    564 
    565 	g_free(iface->name);
    566 	g_free(iface);
    567 
    568 	return TRUE;
    569 }
    570 
    571 static void object_path_unref(DBusConnection *connection, const char *path)
    572 {
    573 	struct generic_data *data = NULL;
    574 
    575 	if (dbus_connection_get_object_path_data(connection, path,
    576 						(void *) &data) == FALSE)
    577 		return;
    578 
    579 	if (data == NULL)
    580 		return;
    581 
    582 	data->refcount--;
    583 
    584 	if (data->refcount > 0)
    585 		return;
    586 
    587 	remove_interface(data, DBUS_INTERFACE_INTROSPECTABLE);
    588 
    589 	invalidate_parent_data(connection, path);
    590 
    591 	dbus_connection_unregister_object_path(connection, path);
    592 }
    593 
    594 static gboolean check_signal(DBusConnection *conn, const char *path,
    595 				const char *interface, const char *name,
    596 				const char **args)
    597 {
    598 	struct generic_data *data = NULL;
    599 	struct interface_data *iface;
    600 	const GDBusSignalTable *signal;
    601 
    602 	*args = NULL;
    603 	if (!dbus_connection_get_object_path_data(conn, path,
    604 					(void *) &data) || data == NULL) {
    605 		error("dbus_connection_emit_signal: path %s isn't registered",
    606 				path);
    607 		return FALSE;
    608 	}
    609 
    610 	iface = find_interface(data->interfaces, interface);
    611 	if (iface == NULL) {
    612 		error("dbus_connection_emit_signal: %s does not implement %s",
    613 				path, interface);
    614 		return FALSE;
    615 	}
    616 
    617 	for (signal = iface->signals; signal && signal->name; signal++) {
    618 		if (!strcmp(signal->name, name)) {
    619 			*args = signal->signature;
    620 			break;
    621 		}
    622 	}
    623 
    624 	if (*args == NULL) {
    625 		error("No signal named %s on interface %s", name, interface);
    626 		return FALSE;
    627 	}
    628 
    629 	return TRUE;
    630 }
    631 
    632 static dbus_bool_t emit_signal_valist(DBusConnection *conn,
    633 						const char *path,
    634 						const char *interface,
    635 						const char *name,
    636 						int first,
    637 						va_list var_args)
    638 {
    639 	DBusMessage *signal;
    640 	dbus_bool_t ret;
    641 	const char *signature, *args;
    642 
    643 	if (!check_signal(conn, path, interface, name, &args))
    644 		return FALSE;
    645 
    646 	signal = dbus_message_new_signal(path, interface, name);
    647 	if (signal == NULL) {
    648 		error("Unable to allocate new %s.%s signal", interface,  name);
    649 		return FALSE;
    650 	}
    651 
    652 	ret = dbus_message_append_args_valist(signal, first, var_args);
    653 	if (!ret)
    654 		goto fail;
    655 
    656 	signature = dbus_message_get_signature(signal);
    657 	if (strcmp(args, signature) != 0) {
    658 		error("%s.%s: expected signature'%s' but got '%s'",
    659 				interface, name, args, signature);
    660 		ret = FALSE;
    661 		goto fail;
    662 	}
    663 
    664 	ret = dbus_connection_send(conn, signal, NULL);
    665 
    666 fail:
    667 	dbus_message_unref(signal);
    668 
    669 	return ret;
    670 }
    671 
    672 gboolean g_dbus_register_interface(DBusConnection *connection,
    673 					const char *path, const char *name,
    674 					const GDBusMethodTable *methods,
    675 					const GDBusSignalTable *signals,
    676 					const GDBusPropertyTable *properties,
    677 					void *user_data,
    678 					GDBusDestroyFunction destroy)
    679 {
    680 	struct generic_data *data;
    681 
    682 	data = object_path_ref(connection, path);
    683 	if (data == NULL)
    684 		return FALSE;
    685 
    686 	if (find_interface(data->interfaces, name)) {
    687 		object_path_unref(connection, path);
    688 		return FALSE;
    689 	}
    690 
    691 	add_interface(data, name, methods, signals,
    692 			properties, user_data, destroy);
    693 
    694 	g_free(data->introspect);
    695 	data->introspect = NULL;
    696 
    697 	return TRUE;
    698 }
    699 
    700 gboolean g_dbus_unregister_interface(DBusConnection *connection,
    701 					const char *path, const char *name)
    702 {
    703 	struct generic_data *data = NULL;
    704 
    705 	if (path == NULL)
    706 		return FALSE;
    707 
    708 	if (dbus_connection_get_object_path_data(connection, path,
    709 						(void *) &data) == FALSE)
    710 		return FALSE;
    711 
    712 	if (data == NULL)
    713 		return FALSE;
    714 
    715 	if (remove_interface(data, name) == FALSE)
    716 		return FALSE;
    717 
    718 	g_free(data->introspect);
    719 	data->introspect = NULL;
    720 
    721 	object_path_unref(connection, path);
    722 
    723 	return TRUE;
    724 }
    725 
    726 gboolean g_dbus_register_security(const GDBusSecurityTable *security)
    727 {
    728 	if (security_table != NULL)
    729 		return FALSE;
    730 
    731 	security_table = security;
    732 
    733 	return TRUE;
    734 }
    735 
    736 gboolean g_dbus_unregister_security(const GDBusSecurityTable *security)
    737 {
    738 	security_table = NULL;
    739 
    740 	return TRUE;
    741 }
    742 
    743 DBusMessage *g_dbus_create_error_valist(DBusMessage *message, const char *name,
    744 					const char *format, va_list args)
    745 {
    746 	char str[1024];
    747 
    748 	vsnprintf(str, sizeof(str), format, args);
    749 
    750 	return dbus_message_new_error(message, name, str);
    751 }
    752 
    753 DBusMessage *g_dbus_create_error(DBusMessage *message, const char *name,
    754 						const char *format, ...)
    755 {
    756 	va_list args;
    757 	DBusMessage *reply;
    758 
    759 	va_start(args, format);
    760 
    761 	reply = g_dbus_create_error_valist(message, name, format, args);
    762 
    763 	va_end(args);
    764 
    765 	return reply;
    766 }
    767 
    768 DBusMessage *g_dbus_create_reply_valist(DBusMessage *message,
    769 						int type, va_list args)
    770 {
    771 	DBusMessage *reply;
    772 
    773 	reply = dbus_message_new_method_return(message);
    774 	if (reply == NULL)
    775 		return NULL;
    776 
    777 	if (dbus_message_append_args_valist(reply, type, args) == FALSE) {
    778 		dbus_message_unref(reply);
    779 		return NULL;
    780 	}
    781 
    782 	return reply;
    783 }
    784 
    785 DBusMessage *g_dbus_create_reply(DBusMessage *message, int type, ...)
    786 {
    787 	va_list args;
    788 	DBusMessage *reply;
    789 
    790 	va_start(args, type);
    791 
    792 	reply = g_dbus_create_reply_valist(message, type, args);
    793 
    794 	va_end(args);
    795 
    796 	return reply;
    797 }
    798 
    799 gboolean g_dbus_send_message(DBusConnection *connection, DBusMessage *message)
    800 {
    801 	dbus_bool_t result;
    802 
    803 	if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
    804 		dbus_message_set_no_reply(message, TRUE);
    805 
    806 	result = dbus_connection_send(connection, message, NULL);
    807 
    808 	dbus_message_unref(message);
    809 
    810 	return result;
    811 }
    812 
    813 gboolean g_dbus_send_reply_valist(DBusConnection *connection,
    814 				DBusMessage *message, int type, va_list args)
    815 {
    816 	DBusMessage *reply;
    817 
    818 	reply = dbus_message_new_method_return(message);
    819 	if (reply == NULL)
    820 		return FALSE;
    821 
    822 	if (dbus_message_append_args_valist(reply, type, args) == FALSE) {
    823 		dbus_message_unref(reply);
    824 		return FALSE;
    825 	}
    826 
    827 	return g_dbus_send_message(connection, reply);
    828 }
    829 
    830 gboolean g_dbus_send_reply(DBusConnection *connection,
    831 				DBusMessage *message, int type, ...)
    832 {
    833 	va_list args;
    834 	gboolean result;
    835 
    836 	va_start(args, type);
    837 
    838 	result = g_dbus_send_reply_valist(connection, message, type, args);
    839 
    840 	va_end(args);
    841 
    842 	return result;
    843 }
    844 
    845 gboolean g_dbus_emit_signal(DBusConnection *connection,
    846 				const char *path, const char *interface,
    847 				const char *name, int type, ...)
    848 {
    849 	va_list args;
    850 	gboolean result;
    851 
    852 	va_start(args, type);
    853 
    854 	result = emit_signal_valist(connection, path, interface,
    855 							name, type, args);
    856 
    857 	va_end(args);
    858 
    859 	return result;
    860 }
    861 
    862 gboolean g_dbus_emit_signal_valist(DBusConnection *connection,
    863 				const char *path, const char *interface,
    864 				const char *name, int type, va_list args)
    865 {
    866 	return emit_signal_valist(connection, path, interface,
    867 							name, type, args);
    868 }
    869