xref: /onnv-gate/usr/src/cmd/hal/hald/hald_dbus.c (revision 10659:933eae95189d)
12912Sartem /***************************************************************************
22912Sartem  * CVSID: $Id$
32912Sartem  *
42912Sartem  * dbus.c : D-BUS interface of HAL daemon
52912Sartem  *
62912Sartem  * Copyright (C) 2003 David Zeuthen, <david@fubar.dk>
72912Sartem  *
82912Sartem  * Licensed under the Academic Free License version 2.1
92912Sartem  *
102912Sartem  * This program is free software; you can redistribute it and/or modify
112912Sartem  * it under the terms of the GNU General Public License as published by
122912Sartem  * the Free Software Foundation; either version 2 of the License, or
132912Sartem  * (at your option) any later version.
142912Sartem  *
152912Sartem  * This program is distributed in the hope that it will be useful,
162912Sartem  * but WITHOUT ANY WARRANTY; without even the implied warranty of
172912Sartem  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
182912Sartem  * GNU General Public License for more details.
192912Sartem  *
202912Sartem  * You should have received a copy of the GNU General Public License
212912Sartem  * along with this program; if not, write to the Free Software
222912Sartem  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
232912Sartem  *
242912Sartem  **************************************************************************/
252912Sartem 
262912Sartem #ifdef HAVE_CONFIG_H
272912Sartem #  include <config.h>
282912Sartem #endif
292912Sartem 
302912Sartem #include <stdlib.h>
312912Sartem #include <stdio.h>
322912Sartem #include <string.h>
332912Sartem #include <unistd.h>
342912Sartem #include <stdarg.h>
352912Sartem #include <stdint.h>
362912Sartem #include <sys/time.h>
372912Sartem 
382912Sartem #include <dbus/dbus.h>
392912Sartem #include <dbus/dbus-glib-lowlevel.h>
402912Sartem 
412912Sartem #include "hald.h"
422912Sartem #include "hald_dbus.h"
432912Sartem #include "device.h"
442912Sartem #include "device_store.h"
452912Sartem #include "device_info.h"
462912Sartem #include "logger.h"
472912Sartem #include "osspec.h"
482912Sartem #include "util.h"
492912Sartem #include "hald_runner.h"
502912Sartem 
512912Sartem #define HALD_DBUS_ADDRESS "unix:tmpdir=" HALD_SOCKET_DIR
522912Sartem 
532912Sartem static DBusConnection *dbus_connection = NULL;
542912Sartem 
552912Sartem static void
562912Sartem raise_error (DBusConnection *connection,
572912Sartem 	     DBusMessage *in_reply_to,
582912Sartem 	     const char *error_name,
592912Sartem 	     char *format, ...) __attribute__((format (printf, 4, 5)));
602912Sartem 
612912Sartem /**
622912Sartem  * @defgroup DaemonErrors Error conditions
632912Sartem  * @ingroup HalDaemon
642912Sartem  * @brief Various error messages the HAL daemon can raise
652912Sartem  * @{
662912Sartem  */
672912Sartem 
682912Sartem /** Raise HAL error
692912Sartem  *
702912Sartem  *  @param  connection          D-Bus connection
712912Sartem  *  @param  in_reply_to         message to report error on
722912Sartem  *  @param  error_name          D-Bus error name
732912Sartem  *  @param  format              printf-style format for error message
742912Sartem  */
752912Sartem static void
raise_error(DBusConnection * connection,DBusMessage * in_reply_to,const char * error_name,char * format,...)762912Sartem raise_error (DBusConnection *connection,
772912Sartem 	     DBusMessage *in_reply_to,
782912Sartem 	     const char *error_name,
792912Sartem 	     char *format, ...)
802912Sartem {
812912Sartem 	char buf[512];
822912Sartem 	DBusMessage *reply;
832912Sartem 
842912Sartem 	va_list args;
852912Sartem 	va_start(args, format);
862912Sartem 	vsnprintf(buf, sizeof buf, format, args);
872912Sartem 	va_end(args);
882912Sartem 
892912Sartem 	HAL_WARNING ((buf));
902912Sartem 	reply = dbus_message_new_error (in_reply_to, error_name, buf);
912912Sartem 	if (reply == NULL)
922912Sartem 		DIE (("No memory"));
932912Sartem 	if (!dbus_connection_send (connection, reply, NULL))
942912Sartem 		DIE (("No memory"));
952912Sartem 	dbus_message_unref (reply);
962912Sartem }
972912Sartem 
982912Sartem /** Raise the org.freedesktop.Hal.NoSuchDevice error
992912Sartem  *
1002912Sartem  *  @param  connection          D-Bus connection
1012912Sartem  *  @param  in_reply_to         message to report error on
1022912Sartem  *  @param  udi                 Unique device id given
1032912Sartem  */
1042912Sartem static void
raise_no_such_device(DBusConnection * connection,DBusMessage * in_reply_to,const char * udi)1052912Sartem raise_no_such_device (DBusConnection *connection,
1062912Sartem 		      DBusMessage *in_reply_to, const char *udi)
1072912Sartem {
1082912Sartem 	raise_error (
1092912Sartem 		connection, in_reply_to,
1102912Sartem 		"org.freedesktop.Hal.NoSuchDevice",
1112912Sartem 		"No device with id %s",
1122912Sartem 		udi
1132912Sartem 	);
1142912Sartem }
1152912Sartem 
1162912Sartem /** Raise the org.freedesktop.Hal.NoSuchProperty error
1172912Sartem  *
1182912Sartem  *  @param  connection          D-Bus connection
1192912Sartem  *  @param  in_reply_to         message to report error on
1202912Sartem  *  @param  device_id           Id of the device
1212912Sartem  *  @param  key                 Key of the property that didn't exist
1222912Sartem  */
1232912Sartem static void
raise_no_such_property(DBusConnection * connection,DBusMessage * in_reply_to,const char * device_id,const char * key)1242912Sartem raise_no_such_property (DBusConnection *connection,
1252912Sartem 			DBusMessage *in_reply_to,
1262912Sartem 			const char *device_id, const char *key)
1272912Sartem {
1282912Sartem 	raise_error (
1292912Sartem 		connection, in_reply_to,
1302912Sartem 		"org.freedesktop.Hal.NoSuchProperty",
1312912Sartem 		"No property %s on device with id %s",
1322912Sartem 		key, device_id
1332912Sartem 	);
1342912Sartem }
1352912Sartem 
1362912Sartem /** Raise the org.freedesktop.Hal.TypeMismatch error
1372912Sartem  *
1382912Sartem  *  @param  connection          D-Bus connection
1392912Sartem  *  @param  in_reply_to         message to report error on
1402912Sartem  *  @param  device_id           Id of the device
1412912Sartem  *  @param  key                 Key of the property
1422912Sartem  */
1432912Sartem static void
raise_property_type_error(DBusConnection * connection,DBusMessage * in_reply_to,const char * device_id,const char * key)1442912Sartem raise_property_type_error (DBusConnection *connection,
1452912Sartem 			   DBusMessage *in_reply_to,
1462912Sartem 			   const char *device_id, const char *key)
1472912Sartem {
1482912Sartem 	raise_error (
1492912Sartem 		connection, in_reply_to,
1502912Sartem 		"org.freedesktop.Hal.TypeMismatch",
1512912Sartem 		"Type mismatch setting property %s on device with id %s",
1522912Sartem 		key, device_id
1532912Sartem 	);
1542912Sartem }
1552912Sartem 
1562912Sartem /** Raise the org.freedesktop.Hal.SyntaxError error
1572912Sartem  *
1582912Sartem  *  @param  connection          D-Bus connection
1592912Sartem  *  @param  in_reply_to         message to report error on
1602912Sartem  *  @param  method_name         Name of the method that was invoked with
1612912Sartem  *                              the wrong signature
1622912Sartem  */
1632912Sartem static void
raise_syntax(DBusConnection * connection,DBusMessage * in_reply_to,const char * method_name)1642912Sartem raise_syntax (DBusConnection *connection,
1652912Sartem 	      DBusMessage *in_reply_to, const char *method_name)
1662912Sartem {
1672912Sartem 	raise_error (
1682912Sartem 		connection, in_reply_to,
1692912Sartem 		"org.freedesktop.Hal.SyntaxError",
1702912Sartem 		"There is a syntax error in the invocation of the method %s",
1712912Sartem 		method_name
1722912Sartem 	);
1732912Sartem }
1742912Sartem 
1752912Sartem /** Raise the org.freedesktop.Hal.DeviceNotLocked error
1762912Sartem  *
1772912Sartem  *  @param  connection          D-Bus connection
1782912Sartem  *  @param  in_reply_to         message to report error on
1792912Sartem  *  @param  device              device which isn't locked
1802912Sartem  */
1812912Sartem static void
raise_device_not_locked(DBusConnection * connection,DBusMessage * in_reply_to,HalDevice * device)1822912Sartem raise_device_not_locked (DBusConnection *connection,
1832912Sartem 			 DBusMessage    *in_reply_to,
1842912Sartem 			 HalDevice      *device)
1852912Sartem {
1862912Sartem 	raise_error (
1872912Sartem 		connection, in_reply_to,
1882912Sartem 		"org.freedesktop.Hal.DeviceNotLocked",
1892912Sartem 		"The device %s is not locked",
1902912Sartem 		 hal_device_get_udi (device)
1912912Sartem 	);
1922912Sartem }
1932912Sartem 
1942912Sartem /** Raise the org.freedesktop.Hal.DeviceAlreadyLocked error
1952912Sartem  *
1962912Sartem  *  @param  connection          D-Bus connection
1972912Sartem  *  @param  in_reply_to         message to report error on
1982912Sartem  *  @param  device              device which isn't locked
1992912Sartem  */
2002912Sartem static void
raise_device_already_locked(DBusConnection * connection,DBusMessage * in_reply_to,HalDevice * device)2012912Sartem raise_device_already_locked (DBusConnection *connection,
2022912Sartem 			     DBusMessage    *in_reply_to,
2032912Sartem 			     HalDevice      *device)
2042912Sartem {
2052912Sartem 	DBusMessage *reply;
2062912Sartem 	const char *reason;
2072912Sartem 
2082912Sartem 	reason = hal_device_property_get_string (device, "info.locked.reason");
2092912Sartem 	HAL_WARNING (("Device %s is already locked: %s",
2102912Sartem 		      hal_device_get_udi (device), reason));
2112912Sartem 
2122912Sartem 
2132912Sartem 	reply = dbus_message_new_error (in_reply_to,
2142912Sartem 					"org.freedesktop.Hal.DeviceAlreadyLocked",
2152912Sartem 					reason);
2162912Sartem 
2172912Sartem 	if (reply == NULL || !dbus_connection_send (connection, reply, NULL))
2182912Sartem 		DIE (("No memory"));
2192912Sartem 
2202912Sartem 	dbus_message_unref (reply);
2212912Sartem }
2222912Sartem 
2232912Sartem /** Raise the org.freedesktop.Hal.BranchAlreadyClaimed error
2242912Sartem  *
2252912Sartem  *  @param  connection          D-Bus connection
2262912Sartem  *  @param  in_reply_to         message to report error on
2272912Sartem  *  @param  udi                 branch which isn't claimed
2282912Sartem  */
2292912Sartem static void
raise_branch_already_claimed(DBusConnection * connection,DBusMessage * in_reply_to,HalDevice * device)2302912Sartem raise_branch_already_claimed (DBusConnection *connection,
2312912Sartem 			     DBusMessage    *in_reply_to,
2322912Sartem 			     HalDevice      *device)
2332912Sartem {
2342912Sartem 	DBusMessage *reply;
2352912Sartem 	const char *claim_service;
2362912Sartem 
2372912Sartem 	claim_service = hal_device_property_get_string (device, "info.claimed.service");
2382912Sartem 	HAL_WARNING (("Branch %s is already claimed by: %s",
2392912Sartem 		      hal_device_get_udi (device), claim_service));
2402912Sartem 
2412912Sartem 
2422912Sartem 	reply = dbus_message_new_error (in_reply_to,
2432912Sartem 					"org.freedesktop.Hal.BranchAlreadyClaimed",
2442912Sartem 					claim_service);
2452912Sartem 
2462912Sartem 	if (reply == NULL || !dbus_connection_send (connection, reply, NULL))
2472912Sartem 		DIE (("No memory"));
2482912Sartem 
2492912Sartem 	dbus_message_unref (reply);
2502912Sartem }
2512912Sartem 
2522912Sartem /** Raise the org.freedesktop.Hal.BranchNotClaimed error
2532912Sartem  *
2542912Sartem  *  @param  connection          D-Bus connection
2552912Sartem  *  @param  in_reply_to         message to report error on
2562912Sartem  *  @param  udi                 branch which isn't claimed
2572912Sartem  */
2582912Sartem static void
raise_branch_not_claimed(DBusConnection * connection,DBusMessage * in_reply_to,HalDevice * device)2592912Sartem raise_branch_not_claimed (DBusConnection *connection,
2602912Sartem 			     DBusMessage    *in_reply_to,
2612912Sartem 			     HalDevice      *device)
2622912Sartem {
2632912Sartem 	raise_error (
2642912Sartem 		connection, in_reply_to,
2652912Sartem 		"org.freedesktop.Hal.BranchNotClaimed",
2662912Sartem 		"The branch %s is not claimed",
2672912Sartem 		 hal_device_get_udi (device)
2682912Sartem 	);
2692912Sartem }
2702912Sartem 
2712912Sartem /** Raise the org.freedesktop.Hal.PermissionDenied error
2722912Sartem  *
2732912Sartem  *  @param  connection          D-Bus connection
2742912Sartem  *  @param  in_reply_to         message to report error on
2752912Sartem  *  @param  message             what you're not allowed to do
2762912Sartem  */
2772912Sartem static void
raise_permission_denied(DBusConnection * connection,DBusMessage * in_reply_to,const char * reason)2782912Sartem raise_permission_denied (DBusConnection *connection,
2792912Sartem 			 DBusMessage    *in_reply_to,
2802912Sartem 			 const char     *reason)
2812912Sartem {
2822912Sartem 	raise_error (
2832912Sartem 		connection, in_reply_to,
2842912Sartem 		"org.freedesktop.Hal.PermissionDenied",
2852912Sartem 		"Permission denied: %s",
2862912Sartem 		 reason
2872912Sartem 	);
2882912Sartem }
2892912Sartem 
2902912Sartem /** @} */
2912912Sartem 
2922912Sartem /**
2932912Sartem  * @defgroup ManagerInterface D-BUS interface org.freedesktop.Hal.Manager
2942912Sartem  * @ingroup HalDaemon
2952912Sartem  * @brief D-BUS interface for querying device objects
2962912Sartem  *
2972912Sartem  * @{
2982912Sartem  */
2992912Sartem 
3002912Sartem static gboolean
foreach_device_get_udi(HalDeviceStore * store,HalDevice * device,gpointer user_data)3012912Sartem foreach_device_get_udi (HalDeviceStore *store, HalDevice *device,
3022912Sartem 			gpointer user_data)
3032912Sartem {
3042912Sartem 	DBusMessageIter *iter = user_data;
3052912Sartem 	const char *udi;
3062912Sartem 
3072912Sartem 	udi = hal_device_get_udi (device);
3082912Sartem 	dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &udi);
3092912Sartem 
3102912Sartem 	return TRUE;
3112912Sartem }
3122912Sartem 
3132912Sartem /** Get all devices.
3142912Sartem  *
3152912Sartem  *  <pre>
3162912Sartem  *  array{object_reference} Manager.GetAllDevices()
3172912Sartem  *  </pre>
3182912Sartem  *
3192912Sartem  *  @param  connection          D-BUS connection
3202912Sartem  *  @param  message             Message
3212912Sartem  *  @return                     What to do with the message
3222912Sartem  */
3232912Sartem DBusHandlerResult
manager_get_all_devices(DBusConnection * connection,DBusMessage * message)3242912Sartem manager_get_all_devices (DBusConnection * connection,
3252912Sartem 			 DBusMessage * message)
3262912Sartem {
3272912Sartem 	DBusMessage *reply;
3282912Sartem 	DBusMessageIter iter;
3292912Sartem 	DBusMessageIter iter_array;
3302912Sartem 
3312912Sartem 	reply = dbus_message_new_method_return (message);
3322912Sartem 	if (reply == NULL)
3332912Sartem 		DIE (("No memory"));
3342912Sartem 
3352912Sartem 	dbus_message_iter_init_append (reply, &iter);
3362912Sartem 	dbus_message_iter_open_container (&iter,
3372912Sartem 					  DBUS_TYPE_ARRAY,
3382912Sartem 					  DBUS_TYPE_STRING_AS_STRING,
3392912Sartem 					  &iter_array);
3402912Sartem 
3412912Sartem 	hal_device_store_foreach (hald_get_gdl (),
3422912Sartem 				  foreach_device_get_udi,
3432912Sartem 				  &iter_array);
3442912Sartem 
3452912Sartem 	dbus_message_iter_close_container (&iter, &iter_array);
3462912Sartem 
3472912Sartem 	if (!dbus_connection_send (connection, reply, NULL))
3482912Sartem 		DIE (("No memory"));
3492912Sartem 
3502912Sartem 	dbus_message_unref (reply);
3512912Sartem 
3522912Sartem 	return DBUS_HANDLER_RESULT_HANDLED;
3532912Sartem }
3542912Sartem 
3552912Sartem typedef struct {
3562912Sartem 	const char *key;
3572912Sartem 	const char *value;
3582912Sartem 	DBusMessageIter *iter;
3592912Sartem } DeviceMatchInfo;
3602912Sartem 
3612912Sartem static gboolean
foreach_device_match_get_udi(HalDeviceStore * store,HalDevice * device,gpointer user_data)3622912Sartem foreach_device_match_get_udi (HalDeviceStore *store, HalDevice *device,
3632912Sartem 			      gpointer user_data)
3642912Sartem {
3652912Sartem 	DeviceMatchInfo *info = user_data;
3662912Sartem 	const char *dev_value;
3672912Sartem 
3682912Sartem 	if (hal_device_property_get_type (device,
3692912Sartem 					  info->key) != DBUS_TYPE_STRING)
3702912Sartem 		return TRUE;
3712912Sartem 
3722912Sartem 	dev_value = hal_device_property_get_string (device, info->key);
3732912Sartem 
3742912Sartem 	if (dev_value != NULL && strcmp (dev_value, info->value) == 0) {
3752912Sartem 		const char *udi;
3762912Sartem 		udi =  hal_device_get_udi (device);
3772912Sartem 		dbus_message_iter_append_basic  (info->iter,
3782912Sartem 						 DBUS_TYPE_STRING,
3792912Sartem 						 &udi);
3802912Sartem 	}
3812912Sartem 
3822912Sartem 	return TRUE;
3832912Sartem }
3842912Sartem 
3852912Sartem static gboolean
foreach_device_match_get_udi_tdl(HalDeviceStore * store,HalDevice * device,gpointer user_data)3862912Sartem foreach_device_match_get_udi_tdl (HalDeviceStore *store, HalDevice *device,
3872912Sartem 				  gpointer user_data)
3882912Sartem {
3892912Sartem 	DeviceMatchInfo *info = user_data;
3902912Sartem 	const char *dev_value;
3912912Sartem 
3922912Sartem 	/* skip devices in the TDL that hasn't got a real UDI yet */
3932912Sartem 	if (strncmp (device->udi, "/org/freedesktop/Hal/devices/temp",
3942912Sartem 		     sizeof ("/org/freedesktop/Hal/devices/temp")) == 0)
3952912Sartem 		return TRUE;
3962912Sartem 
3972912Sartem 	if (hal_device_property_get_type (device,
3982912Sartem 					  info->key) != DBUS_TYPE_STRING)
3992912Sartem 		return TRUE;
4002912Sartem 
4012912Sartem 	dev_value = hal_device_property_get_string (device, info->key);
4022912Sartem 
4032912Sartem 	if (dev_value != NULL && strcmp (dev_value, info->value) == 0) {
4042912Sartem 		const char *udi;
4052912Sartem 		udi = hal_device_get_udi (device);
4062912Sartem 
4072912Sartem 		dbus_message_iter_append_basic (info->iter,
4082912Sartem 						DBUS_TYPE_STRING,
4092912Sartem 						&udi);
4102912Sartem 	}
4112912Sartem 
4122912Sartem 	return TRUE;
4132912Sartem }
4142912Sartem 
4152912Sartem /** Find devices in the GDL where a single string property matches a given
4162912Sartem  *  value. Also returns devices in the TDL that has a non-tmp UDI.
4172912Sartem  *
4182912Sartem  *  <pre>
4192912Sartem  *  array{object_reference} Manager.FindDeviceStringMatch(string key,
4202912Sartem  *                                                        string value)
4212912Sartem  *  </pre>
4222912Sartem  *
4232912Sartem  *  @param  connection          D-BUS connection
4242912Sartem  *  @param  message             Message
4252912Sartem  *  @return                     What to do with the message
4262912Sartem  */
4272912Sartem DBusHandlerResult
manager_find_device_string_match(DBusConnection * connection,DBusMessage * message)4282912Sartem manager_find_device_string_match (DBusConnection * connection,
4292912Sartem 				  DBusMessage * message)
4302912Sartem {
4312912Sartem 	DBusMessage *reply;
4322912Sartem 	DBusMessageIter iter;
4332912Sartem 	DBusMessageIter iter_array;
4342912Sartem 	DBusError error;
4352912Sartem 	const char *key;
4362912Sartem 	const char *value;
4372912Sartem 	DeviceMatchInfo info;
4382912Sartem 
4392912Sartem 	HAL_TRACE (("entering"));
4402912Sartem 
4412912Sartem 	dbus_error_init (&error);
4422912Sartem 	if (!dbus_message_get_args (message, &error,
4432912Sartem 				    DBUS_TYPE_STRING, &key,
4442912Sartem 				    DBUS_TYPE_STRING, &value,
4452912Sartem 				    DBUS_TYPE_INVALID)) {
4462912Sartem 		raise_syntax (connection, message,
4472912Sartem 			      "Manager.FindDeviceStringMatch");
4482912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
4492912Sartem 	}
4502912Sartem 
4512912Sartem 	reply = dbus_message_new_method_return (message);
4522912Sartem 	if (reply == NULL)
4532912Sartem 		DIE (("No memory"));
4542912Sartem 
4552912Sartem 	dbus_message_iter_init_append (reply, &iter);
4562912Sartem 	dbus_message_iter_open_container (&iter,
4572912Sartem 					  DBUS_TYPE_ARRAY,
4582912Sartem 					  DBUS_TYPE_STRING_AS_STRING,
4592912Sartem 					  &iter_array);
4602912Sartem 
4612912Sartem 	info.key = key;
4622912Sartem 	info.value = value;
4632912Sartem 	info.iter = &iter_array;
4642912Sartem 
4652912Sartem 	hal_device_store_foreach (hald_get_gdl (),
4662912Sartem 				  foreach_device_match_get_udi,
4672912Sartem 				  &info);
4682912Sartem 
4692912Sartem 	/* Also returns devices in the TDL that has a non-tmp UDI */
4702912Sartem 	hal_device_store_foreach (hald_get_tdl (),
4712912Sartem 				  foreach_device_match_get_udi_tdl,
4722912Sartem 				  &info);
4732912Sartem 
4742912Sartem 	dbus_message_iter_close_container (&iter, &iter_array);
4752912Sartem 
4762912Sartem 	if (!dbus_connection_send (connection, reply, NULL))
4772912Sartem 		DIE (("No memory"));
4782912Sartem 
4792912Sartem 	dbus_message_unref (reply);
4802912Sartem 
4812912Sartem 	return DBUS_HANDLER_RESULT_HANDLED;
4822912Sartem }
4832912Sartem 
4842912Sartem typedef struct {
4852912Sartem 	const char *capability;
4862912Sartem 	DBusMessageIter *iter;
4872912Sartem } DeviceCapabilityInfo;
4882912Sartem 
4892912Sartem static gboolean
foreach_device_by_capability(HalDeviceStore * store,HalDevice * device,gpointer user_data)4902912Sartem foreach_device_by_capability (HalDeviceStore *store, HalDevice *device, gpointer user_data)
4912912Sartem {
4922912Sartem 	DeviceCapabilityInfo *info = (DeviceCapabilityInfo *) user_data;
4932912Sartem 
4942912Sartem 	if (hal_device_has_capability (device, info->capability)) {
4952912Sartem 		dbus_message_iter_append_basic (info->iter,
4962912Sartem 						DBUS_TYPE_STRING,
4972912Sartem 						&(device->udi));
4982912Sartem 	}
4992912Sartem 
5002912Sartem 	return TRUE;
5012912Sartem }
5022912Sartem 
5032912Sartem /** Find devices in the GDL with a given capability.
5042912Sartem  *
5052912Sartem  *  <pre>
5062912Sartem  *  array{object_reference} Manager.FindDeviceByCapability(string capability)
5072912Sartem  *  </pre>
5082912Sartem  *
5092912Sartem  *  @param  connection          D-BUS connection
5102912Sartem  *  @param  message             Message
5112912Sartem  *  @return                     What to do with the message
5122912Sartem  */
5132912Sartem DBusHandlerResult
manager_find_device_by_capability(DBusConnection * connection,DBusMessage * message)5142912Sartem manager_find_device_by_capability (DBusConnection * connection,
5152912Sartem 				   DBusMessage * message)
5162912Sartem {
5172912Sartem 	DBusMessage *reply;
5182912Sartem 	DBusMessageIter iter;
5192912Sartem 	DBusMessageIter iter_array;
5202912Sartem 	DBusError error;
5212912Sartem 	const char *capability;
5222912Sartem 	DeviceCapabilityInfo info;
5232912Sartem 
5242912Sartem 	HAL_TRACE (("entering"));
5252912Sartem 
5262912Sartem 	dbus_error_init (&error);
5272912Sartem 	if (!dbus_message_get_args (message, &error,
5282912Sartem 				    DBUS_TYPE_STRING, &capability,
5292912Sartem 				    DBUS_TYPE_INVALID)) {
5302912Sartem 		raise_syntax (connection, message,
5312912Sartem 			      "Manager.FindDeviceByCapability");
5322912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
5332912Sartem 	}
5342912Sartem 
5352912Sartem 	reply = dbus_message_new_method_return (message);
5362912Sartem 	if (reply == NULL)
5372912Sartem 		DIE (("No memory"));
5382912Sartem 
5392912Sartem 	dbus_message_iter_init_append (reply, &iter);
5402912Sartem 	dbus_message_iter_open_container (&iter,
5412912Sartem 					  DBUS_TYPE_ARRAY,
5422912Sartem 					  DBUS_TYPE_STRING_AS_STRING,
5432912Sartem 					  &iter_array);
5442912Sartem 
5452912Sartem 	info.capability = capability;
5462912Sartem 	info.iter = &iter_array;
5472912Sartem 
5482912Sartem 	hal_device_store_foreach (hald_get_gdl (),
5492912Sartem 				  foreach_device_by_capability,
5502912Sartem 				  &info);
5512912Sartem 
5522912Sartem 	dbus_message_iter_close_container (&iter, &iter_array);
5532912Sartem 
5542912Sartem 	if (!dbus_connection_send (connection, reply, NULL))
5552912Sartem 		DIE (("No memory"));
5562912Sartem 
5572912Sartem 	dbus_message_unref (reply);
5582912Sartem 
5592912Sartem 	return DBUS_HANDLER_RESULT_HANDLED;
5602912Sartem }
5612912Sartem 
5622912Sartem 
5632912Sartem /** Determine if a device exists.
5642912Sartem  *
5652912Sartem  *  <pre>
5662912Sartem  *  bool Manager.DeviceExists(string udi)
5672912Sartem  *  </pre>
5682912Sartem  *
5692912Sartem  *  @param  connection          D-BUS connection
5702912Sartem  *  @param  message             Message
5712912Sartem  *  @return                     What to do with the message
5722912Sartem  */
5732912Sartem DBusHandlerResult
manager_device_exists(DBusConnection * connection,DBusMessage * message)5742912Sartem manager_device_exists (DBusConnection * connection, DBusMessage * message)
5752912Sartem {
5762912Sartem 	DBusMessage *reply;
5772912Sartem 	DBusMessageIter iter;
5782912Sartem 	DBusError error;
5792912Sartem 	HalDevice *d;
5802912Sartem 	const char *udi;
5812912Sartem 	dbus_bool_t b;
5822912Sartem 
5832912Sartem 	dbus_error_init (&error);
5842912Sartem 	if (!dbus_message_get_args (message, &error,
5852912Sartem 				    DBUS_TYPE_STRING, &udi,
5862912Sartem 				    DBUS_TYPE_INVALID)) {
5872912Sartem 		raise_syntax (connection, message, "Manager.DeviceExists");
5882912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
5892912Sartem 	}
5902912Sartem 
5912912Sartem 	HAL_TRACE (("entering, udi=%s", udi));
5922912Sartem 
5932912Sartem 	d = hal_device_store_find (hald_get_gdl (), udi);
5942912Sartem 
5952912Sartem 	if (d == NULL)
5962912Sartem 		d = hal_device_store_find (hald_get_tdl (), udi);
5972912Sartem 
5982912Sartem 	reply = dbus_message_new_method_return (message);
5992912Sartem 	dbus_message_iter_init_append (reply, &iter);
6002912Sartem 	b = d != NULL;
6012912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &b);
6022912Sartem 
6032912Sartem 	if (reply == NULL)
6042912Sartem 		DIE (("No memory"));
6052912Sartem 
6062912Sartem 	if (!dbus_connection_send (connection, reply, NULL))
6072912Sartem 		DIE (("No memory"));
6082912Sartem 
6092912Sartem 	dbus_message_unref (reply);
6102912Sartem 	return DBUS_HANDLER_RESULT_HANDLED;
6112912Sartem }
6122912Sartem 
6132912Sartem /** Send signal DeviceAdded(string udi) on the org.freedesktop.Hal.Manager
6142912Sartem  *  interface on the object /org/freedesktop/Hal/Manager.
6152912Sartem  *
6162912Sartem  *  @param  device              The HalDevice added
6172912Sartem  */
6182912Sartem void
manager_send_signal_device_added(HalDevice * device)6192912Sartem manager_send_signal_device_added (HalDevice *device)
6202912Sartem {
6212912Sartem 	const char *udi = hal_device_get_udi (device);
6222912Sartem 	DBusMessage *message;
6232912Sartem 	DBusMessageIter iter;
6242912Sartem 
6252912Sartem 	if (dbus_connection == NULL)
6262912Sartem 		goto out;
6272912Sartem 
6282912Sartem 	HAL_TRACE (("entering, udi=%s", udi));
6292912Sartem 
6302912Sartem 	message = dbus_message_new_signal ("/org/freedesktop/Hal/Manager",
6312912Sartem 					   "org.freedesktop.Hal.Manager",
6322912Sartem 					   "DeviceAdded");
6332912Sartem 
6342912Sartem 	dbus_message_iter_init_append (message, &iter);
6352912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &udi);
6362912Sartem 
6372912Sartem 	if (!dbus_connection_send (dbus_connection, message, NULL))
6382912Sartem 		DIE (("error broadcasting message"));
6392912Sartem 
6402912Sartem 	dbus_message_unref (message);
6412912Sartem 
6422912Sartem out:
6432912Sartem 	;
6442912Sartem }
6452912Sartem 
6462912Sartem /** Send signal DeviceRemoved(string udi) on the org.freedesktop.Hal.Manager
6472912Sartem  *  interface on the object /org/freedesktop/Hal/Manager.
6482912Sartem  *
6492912Sartem  *  @param  device              The HalDevice removed
6502912Sartem  */
6512912Sartem void
manager_send_signal_device_removed(HalDevice * device)6522912Sartem manager_send_signal_device_removed (HalDevice *device)
6532912Sartem {
6542912Sartem 	const char *udi = hal_device_get_udi (device);
6552912Sartem 	DBusMessage *message;
6562912Sartem 	DBusMessageIter iter;
6572912Sartem 
6582912Sartem 	if (dbus_connection == NULL)
6592912Sartem 		goto out;
6602912Sartem 
6612912Sartem 	HAL_TRACE (("entering, udi=%s", udi));
6622912Sartem 
6632912Sartem 	message = dbus_message_new_signal ("/org/freedesktop/Hal/Manager",
6642912Sartem 					   "org.freedesktop.Hal.Manager",
6652912Sartem 					   "DeviceRemoved");
6662912Sartem 
6672912Sartem 	dbus_message_iter_init_append (message, &iter);
6682912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &udi);
6692912Sartem 
6702912Sartem 	if (!dbus_connection_send (dbus_connection, message, NULL))
6712912Sartem 		DIE (("error broadcasting message"));
6722912Sartem 
6732912Sartem 	dbus_message_unref (message);
6742912Sartem out:
6752912Sartem 	;
6762912Sartem }
6772912Sartem 
6782912Sartem /** Send signal NewCapability(string udi, string capability) on the
6792912Sartem  *  org.freedesktop.Hal.Manager interface on the object
6802912Sartem  *  /org/freedesktop/Hal/Manager.
6812912Sartem  *
6822912Sartem  *  @param  udi                 Unique Device Id
6832912Sartem  *  @param  capability          Capability
6842912Sartem  */
6852912Sartem void
manager_send_signal_new_capability(HalDevice * device,const char * capability)6862912Sartem manager_send_signal_new_capability (HalDevice *device,
6872912Sartem 				    const char *capability)
6882912Sartem {
6892912Sartem 	const char *udi = hal_device_get_udi (device);
6902912Sartem 	DBusMessage *message;
6912912Sartem 	DBusMessageIter iter;
6922912Sartem 
6932912Sartem 	if (dbus_connection == NULL)
6942912Sartem 		goto out;
6952912Sartem 
6962912Sartem 	HAL_TRACE (("entering, udi=%s, cap=%s", udi, capability));
6972912Sartem 
6982912Sartem 	message = dbus_message_new_signal ("/org/freedesktop/Hal/Manager",
6992912Sartem 					   "org.freedesktop.Hal.Manager",
7002912Sartem 					   "NewCapability");
7012912Sartem 
7022912Sartem 	dbus_message_iter_init_append (message, &iter);
7032912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &udi);
7042912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &capability);
7052912Sartem 
7062912Sartem 	if (!dbus_connection_send (dbus_connection, message, NULL))
7072912Sartem 		DIE (("error broadcasting message"));
7082912Sartem 
7092912Sartem 	dbus_message_unref (message);
7102912Sartem out:
7112912Sartem 	;
7122912Sartem }
7132912Sartem 
7142912Sartem /** @} */
7152912Sartem 
7162912Sartem /**
7172912Sartem  * @defgroup DeviceInterface D-BUS interface org.freedesktop.Hal.Device
7182912Sartem  * @ingroup HalDaemon
7192912Sartem  * @brief D-BUS interface for generic device operations
7202912Sartem  * @{
7212912Sartem  */
7222912Sartem 
7232912Sartem static gboolean
foreach_property_append(HalDevice * device,HalProperty * p,gpointer user_data)7242912Sartem foreach_property_append (HalDevice *device, HalProperty *p,
7252912Sartem 			 gpointer user_data)
7262912Sartem {
7272912Sartem 	DBusMessageIter *iter;
7282912Sartem 	DBusMessageIter iter_dict_entry;
7292912Sartem 	const char *key;
7302912Sartem 	int type;
7312912Sartem 
7322912Sartem 	iter = (DBusMessageIter *)user_data;
7332912Sartem 
7342912Sartem 	dbus_message_iter_open_container (iter,
7352912Sartem 					  DBUS_TYPE_DICT_ENTRY,
7362912Sartem 					  NULL,
7372912Sartem 					  &iter_dict_entry);
7382912Sartem 
7392912Sartem 	key = hal_property_get_key (p);
7402912Sartem 	type = hal_property_get_type (p);
7412912Sartem 
7422912Sartem 	dbus_message_iter_append_basic (&iter_dict_entry, DBUS_TYPE_STRING, &key);
7432912Sartem 
7442912Sartem 	switch (type) {
7452912Sartem 	case HAL_PROPERTY_TYPE_STRING:
7462912Sartem 	{
7472912Sartem 		DBusMessageIter iter_var;
7482912Sartem 		const char *v;
7492912Sartem 
7502912Sartem 		v = hal_property_get_string (p);
7512912Sartem 
7522912Sartem 		dbus_message_iter_open_container (&iter_dict_entry,
7532912Sartem 						  DBUS_TYPE_VARIANT,
7542912Sartem 						  DBUS_TYPE_STRING_AS_STRING,
7552912Sartem 						  &iter_var);
7562912Sartem 
7572912Sartem 		dbus_message_iter_append_basic (&iter_var,
7582912Sartem 						DBUS_TYPE_STRING,
7592912Sartem 						&v);
7602912Sartem 
7612912Sartem 		dbus_message_iter_close_container (&iter_dict_entry,
7622912Sartem 						   &iter_var);
7632912Sartem 		break;
7642912Sartem 	}
7652912Sartem 	case HAL_PROPERTY_TYPE_INT32:
7662912Sartem 	{
7672912Sartem 		DBusMessageIter iter_var;
7682912Sartem 		dbus_int32_t v;
7692912Sartem 
7702912Sartem 		v = hal_property_get_int (p);
7712912Sartem 
7722912Sartem 		dbus_message_iter_open_container (&iter_dict_entry,
7732912Sartem 						  DBUS_TYPE_VARIANT,
7742912Sartem 						  DBUS_TYPE_INT32_AS_STRING,
7752912Sartem 						  &iter_var);
7762912Sartem 
7772912Sartem 		dbus_message_iter_append_basic (&iter_var,
7782912Sartem 						DBUS_TYPE_INT32,
7792912Sartem 						&v);
7802912Sartem 
7812912Sartem 		dbus_message_iter_close_container (&iter_dict_entry,
7822912Sartem 						   &iter_var);
7832912Sartem 		break;
7842912Sartem 	}
7852912Sartem 	case HAL_PROPERTY_TYPE_UINT64:
7862912Sartem 	{
7872912Sartem 		DBusMessageIter iter_var;
7882912Sartem 		dbus_uint64_t v;
7892912Sartem 
7902912Sartem 		v = hal_property_get_uint64 (p);
7912912Sartem 
7922912Sartem 		dbus_message_iter_open_container (&iter_dict_entry,
7932912Sartem 						  DBUS_TYPE_VARIANT,
7942912Sartem 						  DBUS_TYPE_UINT64_AS_STRING,
7952912Sartem 						  &iter_var);
7962912Sartem 
7972912Sartem 		dbus_message_iter_append_basic (&iter_var,
7982912Sartem 						DBUS_TYPE_UINT64,
7992912Sartem 						&v);
8002912Sartem 
8012912Sartem 		dbus_message_iter_close_container (&iter_dict_entry,
8022912Sartem 						   &iter_var);
8032912Sartem 		break;
8042912Sartem 	}
8052912Sartem 	case HAL_PROPERTY_TYPE_DOUBLE:
8062912Sartem 	{
8072912Sartem 		DBusMessageIter iter_var;
8082912Sartem 		double v;
8092912Sartem 
8102912Sartem 		v = hal_property_get_double (p);
8112912Sartem 
8122912Sartem 		dbus_message_iter_open_container (&iter_dict_entry,
8132912Sartem 						  DBUS_TYPE_VARIANT,
8142912Sartem 						  DBUS_TYPE_DOUBLE_AS_STRING,
8152912Sartem 						  &iter_var);
8162912Sartem 
8172912Sartem 		dbus_message_iter_append_basic (&iter_var,
8182912Sartem 						DBUS_TYPE_DOUBLE,
8192912Sartem 						&v);
8202912Sartem 
8212912Sartem 		dbus_message_iter_close_container (&iter_dict_entry,
8222912Sartem 						   &iter_var);
8232912Sartem 		break;
8242912Sartem 	}
8252912Sartem 	case HAL_PROPERTY_TYPE_BOOLEAN:
8262912Sartem 	{
8272912Sartem 		DBusMessageIter iter_var;
8282912Sartem 		dbus_bool_t v;
8292912Sartem 
8302912Sartem 		v = hal_property_get_bool (p);
8312912Sartem 
8322912Sartem 		dbus_message_iter_open_container (&iter_dict_entry,
8332912Sartem 						  DBUS_TYPE_VARIANT,
8342912Sartem 						  DBUS_TYPE_BOOLEAN_AS_STRING,
8352912Sartem 						  &iter_var);
8362912Sartem 
8372912Sartem 		dbus_message_iter_append_basic (&iter_var,
8382912Sartem 						DBUS_TYPE_BOOLEAN,
8392912Sartem 						&v);
8402912Sartem 
8412912Sartem 		dbus_message_iter_close_container (&iter_dict_entry,
8422912Sartem 						   &iter_var);
8432912Sartem 		break;
8442912Sartem 	}
8452912Sartem 	case HAL_PROPERTY_TYPE_STRLIST:
8462912Sartem 	{
8472912Sartem 		DBusMessageIter iter_var, iter_array;
8482912Sartem 		GSList *iter;
8492912Sartem 
8502912Sartem 		dbus_message_iter_open_container (&iter_dict_entry,
8512912Sartem 						  DBUS_TYPE_VARIANT,
8522912Sartem 						  DBUS_TYPE_ARRAY_AS_STRING
8532912Sartem 						  DBUS_TYPE_STRING_AS_STRING,
8542912Sartem 						  &iter_var);
8552912Sartem 
8562912Sartem 		dbus_message_iter_open_container (&iter_var,
8572912Sartem 						  DBUS_TYPE_ARRAY,
8582912Sartem 						  DBUS_TYPE_STRING_AS_STRING,
8592912Sartem 						  &iter_array);
8602912Sartem 
8612912Sartem 		for (iter = hal_property_get_strlist (p); iter != NULL; iter = iter->next) {
8622912Sartem 
8632912Sartem 			const char *v;
8642912Sartem 			v = (const char *) iter->data;
8652912Sartem 
8662912Sartem 			dbus_message_iter_append_basic (&iter_array,
8672912Sartem 							DBUS_TYPE_STRING,
8682912Sartem 							&v);
8692912Sartem 		}
8702912Sartem 
8712912Sartem 		dbus_message_iter_close_container (&iter_var,
8722912Sartem 						   &iter_array);
8732912Sartem 
8742912Sartem 		dbus_message_iter_close_container (&iter_dict_entry,
8752912Sartem 						   &iter_var);
8762912Sartem 		break;
8772912Sartem 	}
8782912Sartem 
8792912Sartem 	default:
8802912Sartem 		HAL_WARNING (("Unknown property type 0x%04x", type));
8812912Sartem 		break;
8822912Sartem 	}
8832912Sartem 
8842912Sartem 	dbus_message_iter_close_container (iter, &iter_dict_entry);
8852912Sartem 
8862912Sartem 
8872912Sartem 	return TRUE;
8882912Sartem }
8892912Sartem 
8902912Sartem 
8912912Sartem 
8922912Sartem /** Get all properties on a device.
8932912Sartem  *
8942912Sartem  *  <pre>
8952912Sartem  *  map{string, any} Device.GetAllProperties()
8962912Sartem  *
8972912Sartem  *    raises org.freedesktop.Hal.NoSuchDevice
8982912Sartem  *  </pre>
8992912Sartem  *
9002912Sartem  *  @param  connection          D-BUS connection
9012912Sartem  *  @param  message             Message
9022912Sartem  *  @return                     What to do with the message
9032912Sartem  */
9042912Sartem DBusHandlerResult
device_get_all_properties(DBusConnection * connection,DBusMessage * message)9052912Sartem device_get_all_properties (DBusConnection * connection,
9062912Sartem 			   DBusMessage * message)
9072912Sartem {
9082912Sartem 	DBusMessage *reply;
9092912Sartem 	DBusMessageIter iter;
9102912Sartem 	DBusMessageIter iter_dict;
9112912Sartem 	HalDevice *d;
9122912Sartem 	const char *udi;
9132912Sartem 
9142912Sartem 	udi = dbus_message_get_path (message);
9152912Sartem 
9162912Sartem 	HAL_TRACE (("entering, udi=%s", udi));
9172912Sartem 
9182912Sartem 	d = hal_device_store_find (hald_get_gdl (), udi);
9192912Sartem 	if (d == NULL)
9202912Sartem 		d = hal_device_store_find (hald_get_tdl (), udi);
9212912Sartem 
9222912Sartem 	if (d == NULL) {
9232912Sartem 		raise_no_such_device (connection, message, udi);
9242912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
9252912Sartem 	}
9262912Sartem 
9272912Sartem 	reply = dbus_message_new_method_return (message);
9282912Sartem 	if (reply == NULL)
9292912Sartem 		DIE (("No memory"));
9302912Sartem 
9312912Sartem 	dbus_message_iter_init_append (reply, &iter);
9322912Sartem 
9332912Sartem 	dbus_message_iter_open_container (&iter,
9342912Sartem 					  DBUS_TYPE_ARRAY,
9352912Sartem 					  DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
9362912Sartem 					  DBUS_TYPE_STRING_AS_STRING
9372912Sartem 					  DBUS_TYPE_VARIANT_AS_STRING
9382912Sartem 					  DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
9392912Sartem 					  &iter_dict);
9402912Sartem 
9412912Sartem 	hal_device_property_foreach (d,
9422912Sartem 				     foreach_property_append,
9432912Sartem 				     &iter_dict);
9442912Sartem 
9452912Sartem 	dbus_message_iter_close_container (&iter, &iter_dict);
9462912Sartem 
9472912Sartem 	if (!dbus_connection_send (connection, reply, NULL))
9482912Sartem 		DIE (("No memory"));
9492912Sartem 
9502912Sartem 	dbus_message_unref (reply);
9512912Sartem 
9522912Sartem 	return DBUS_HANDLER_RESULT_HANDLED;
9532912Sartem }
9542912Sartem 
9552912Sartem #ifdef sun
9562912Sartem #include <sys/stat.h>
9572912Sartem static dbus_bool_t
user_at_console(unsigned long uid)9582912Sartem user_at_console(unsigned long uid)
9592912Sartem {
9602912Sartem 	struct stat st;
9612912Sartem 
9622912Sartem 	return ((stat("/dev/console", &st) == 0) && (st.st_uid == uid));
9632912Sartem }
9642912Sartem #endif /* sun */
9652912Sartem 
9662912Sartem static dbus_bool_t
sender_has_privileges(DBusConnection * connection,DBusMessage * message)9672912Sartem sender_has_privileges (DBusConnection *connection, DBusMessage *message)
9682912Sartem {
9692912Sartem 	DBusError error;
9702912Sartem 	unsigned long user_uid;
9712912Sartem 	const char *user_base_svc;
9722912Sartem 	dbus_bool_t ret;
9732912Sartem 
9742912Sartem 	ret = FALSE;
9752912Sartem 
9762912Sartem 	user_base_svc = dbus_message_get_sender (message);
9772912Sartem 	if (user_base_svc == NULL) {
9782912Sartem 		HAL_WARNING (("Cannot determine base service of caller"));
9792912Sartem 		goto out;
9802912Sartem 	}
9812912Sartem 
9822912Sartem 	HAL_DEBUG (("base_svc = %s", user_base_svc));
9832912Sartem 
9842912Sartem 	dbus_error_init (&error);
9852912Sartem 	user_uid = dbus_bus_get_unix_user (connection, user_base_svc, &error);
9862912Sartem 	if (user_uid == (unsigned long) -1 || dbus_error_is_set (&error)) {
9872912Sartem 		HAL_WARNING (("Could not get uid for connection: %s %s", error.name, error.message));
9882912Sartem 		dbus_error_free (&error);
9892912Sartem 		goto out;
9902912Sartem 	}
9912912Sartem 
9922912Sartem 	HAL_INFO (("uid for caller is %ld", user_uid));
9932912Sartem 
9942912Sartem 	if (user_uid != 0 && user_uid != geteuid()) {
9952912Sartem #ifdef sun
9962912Sartem 		if (dbus_message_is_method_call (message,
9972912Sartem 						"org.freedesktop.Hal.Device",
9982912Sartem 						"Rescan")) {
9992912Sartem 			if (user_at_console(user_uid)) {
10002912Sartem 				ret = TRUE;
10012912Sartem 				goto out;
10022912Sartem 			}
10032912Sartem 		}
10042912Sartem #endif
10052912Sartem 		HAL_WARNING (("uid %d is not privileged", user_uid));
10062912Sartem 		goto out;
10072912Sartem 	}
10082912Sartem 
10092912Sartem 	ret = TRUE;
10102912Sartem 
10112912Sartem out:
10122912Sartem 	return ret;
10132912Sartem }
10142912Sartem 
10152912Sartem 
10162912Sartem /** Set multiple properties on a device in an atomic fashion.
10172912Sartem  *
10182912Sartem  *  <pre>
10192912Sartem  *  Device.GetAllProperties(map{string, any} properties)
10202912Sartem  *
10212912Sartem  *    raises org.freedesktop.Hal.NoSuchDevice
10222912Sartem  *  </pre>
10232912Sartem  *
10242912Sartem  *  @param  connection          D-BUS connection
10252912Sartem  *  @param  message             Message
10262912Sartem  *  @return                     What to do with the message
10272912Sartem  */
10282912Sartem static DBusHandlerResult
device_set_multiple_properties(DBusConnection * connection,DBusMessage * message,dbus_bool_t local_interface)10292912Sartem device_set_multiple_properties (DBusConnection *connection, DBusMessage *message, dbus_bool_t local_interface)
10302912Sartem {
10312912Sartem 	DBusMessage *reply;
10322912Sartem 	DBusMessageIter iter;
10332912Sartem 	DBusMessageIter dict_iter;
10342912Sartem 	HalDevice *d;
10352912Sartem 	const char *udi;
10362912Sartem 
10372912Sartem 	udi = dbus_message_get_path (message);
10382912Sartem 
10392912Sartem 	HAL_TRACE (("entering, udi=%s", udi));
10402912Sartem 
10412912Sartem 	d = hal_device_store_find (hald_get_gdl (), udi);
10422912Sartem 	if (d == NULL)
10432912Sartem 		d = hal_device_store_find (hald_get_tdl (), udi);
10442912Sartem 
10452912Sartem 	if (d == NULL) {
10462912Sartem 		raise_no_such_device (connection, message, udi);
10472912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
10482912Sartem 	}
10492912Sartem 
10502912Sartem 	if (!local_interface && !sender_has_privileges (connection, message)) {
10512912Sartem 		raise_permission_denied (connection, message, "SetProperty: not privileged");
10522912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
10532912Sartem 	}
10542912Sartem 
10552912Sartem 	dbus_message_iter_init (message, &iter);
10562912Sartem 
10572912Sartem 	if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY  &&
10582912Sartem 	    dbus_message_iter_get_element_type (&iter) != DBUS_TYPE_DICT_ENTRY) {
10592912Sartem 		HAL_ERROR (("error, expecting an array of dict entries", __FILE__, __LINE__));
10602912Sartem 		raise_syntax (connection, message, udi);
10612912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
10622912Sartem 	}
10632912Sartem 
10642912Sartem 	dbus_message_iter_recurse (&iter, &dict_iter);
10652912Sartem 
10662912Sartem 	/* update atomically */
10672912Sartem 	device_property_atomic_update_begin ();
10682912Sartem 
10692912Sartem 	while (dbus_message_iter_get_arg_type (&dict_iter) == DBUS_TYPE_DICT_ENTRY)
10702912Sartem 	{
10712912Sartem 		DBusMessageIter dict_entry_iter, var_iter, array_iter;
10722912Sartem 		const char *key;
10732912Sartem 		int change_type;
10742912Sartem 		dbus_bool_t rc;
10752912Sartem 
10762912Sartem 		dbus_message_iter_recurse (&dict_iter, &dict_entry_iter);
10772912Sartem 		dbus_message_iter_get_basic (&dict_entry_iter, &key);
10782912Sartem 
10792912Sartem 		dbus_message_iter_next (&dict_entry_iter);
10802912Sartem 		dbus_message_iter_recurse (&dict_entry_iter, &var_iter);
10812912Sartem 		change_type = dbus_message_iter_get_arg_type (&var_iter);
10822912Sartem 
10832912Sartem 		rc = FALSE;
10842912Sartem 
10852912Sartem 		switch (change_type) {
10862912Sartem 		case DBUS_TYPE_ARRAY:
10872912Sartem 			if (dbus_message_iter_get_element_type (&var_iter) != DBUS_TYPE_STRING) {
10882912Sartem 				/* TODO: error */
10892912Sartem 			}
10902912Sartem 			dbus_message_iter_recurse (&var_iter, &array_iter);
10912912Sartem 
10922912Sartem 			hal_device_property_strlist_clear (d, key);
10932912Sartem 
10942912Sartem 			while (dbus_message_iter_get_arg_type (&array_iter) == DBUS_TYPE_STRING) {
10952912Sartem 				const char *v;
10962912Sartem 				dbus_message_iter_get_basic (&array_iter, &v);
10972912Sartem 				HAL_INFO ((" strlist elem %s -> %s", key, v));
10982912Sartem 				rc = hal_device_property_strlist_append (d, key, v);
10992912Sartem 				dbus_message_iter_next (&array_iter);
11002912Sartem 			}
11012912Sartem 
11022912Sartem 			break;
11032912Sartem 		case DBUS_TYPE_STRING:
11042912Sartem 		{
11052912Sartem 			const char *v;
11062912Sartem 			dbus_message_iter_get_basic (&var_iter, &v);
11072912Sartem 			HAL_INFO (("%s -> %s", key, v));
11082912Sartem 			rc = hal_device_property_set_string (d, key, v);
11092912Sartem 			break;
11102912Sartem 		}
11112912Sartem 		case DBUS_TYPE_INT32:
11122912Sartem 		{
11132912Sartem 			dbus_int32_t v;
11142912Sartem 			dbus_message_iter_get_basic (&var_iter, &v);
11152912Sartem 			HAL_INFO (("%s -> %d", key, v));
11162912Sartem 			rc = hal_device_property_set_int (d, key, v);
11172912Sartem 			break;
11182912Sartem 		}
11192912Sartem 		case DBUS_TYPE_UINT64:
11202912Sartem 		{
11212912Sartem 			dbus_uint64_t v;
11222912Sartem 			dbus_message_iter_get_basic (&var_iter, &v);
11232912Sartem 			HAL_INFO (("%s -> %lld", key, v));
11242912Sartem 			rc = hal_device_property_set_uint64 (d, key, v);
11252912Sartem 			break;
11262912Sartem 		}
11272912Sartem 		case DBUS_TYPE_DOUBLE:
11282912Sartem 		{
11292912Sartem 			double v;
11302912Sartem 			dbus_message_iter_get_basic (&var_iter, &v);
11312912Sartem 			HAL_INFO (("%s -> %g", key, v));
11322912Sartem 			rc = hal_device_property_set_double (d, key, v);
11332912Sartem 			break;
11342912Sartem 		}
11352912Sartem 		case DBUS_TYPE_BOOLEAN:
11362912Sartem 		{
11372912Sartem 			gboolean v;
11382912Sartem 			dbus_message_iter_get_basic (&var_iter, &v);
11392912Sartem 			HAL_INFO (("%s -> %s", key, v ? "True" : "False"));
11402912Sartem 			rc = hal_device_property_set_bool (d, key, v);
11412912Sartem 			break;
11422912Sartem 		}
11432912Sartem 		default:
11442912Sartem 			/* TODO: error */
11452912Sartem 			break;
11462912Sartem 		}
11472912Sartem 
11482912Sartem 		/* TODO: error out on rc==FALSE? */
11492912Sartem 
11502912Sartem 		dbus_message_iter_next (&dict_iter);
11512912Sartem 	}
11522912Sartem 
11532912Sartem 	device_property_atomic_update_end ();
11542912Sartem 
11552912Sartem 
11562912Sartem 	reply = dbus_message_new_method_return (message);
11572912Sartem 	if (reply == NULL)
11582912Sartem 		DIE (("No memory"));
11592912Sartem 
11602912Sartem 	if (!dbus_connection_send (connection, reply, NULL))
11612912Sartem 		DIE (("No memory"));
11622912Sartem 
11632912Sartem 	dbus_message_unref (reply);
11642912Sartem 	return DBUS_HANDLER_RESULT_HANDLED;
11652912Sartem }
11662912Sartem 
11672912Sartem 
11682912Sartem /** Get a property on a device.
11692912Sartem  *
11702912Sartem  *  <pre>
11712912Sartem  *  any Device.GetProperty(string key)
11722912Sartem  *  string Device.GetPropertyString(string key)
11732912Sartem  *  int Device.GetPropertyInteger(string key)
11742912Sartem  *  bool Device.GetPropertyBoolean(string key)
11752912Sartem  *  double Device.GetPropertyDouble(string key)
11762912Sartem  *
11772912Sartem  *    raises org.freedesktop.Hal.NoSuchDevice,
11782912Sartem  *           org.freedesktop.Hal.NoSuchProperty
11792912Sartem  *  </pre>
11802912Sartem  *
11812912Sartem  *  @param  connection          D-BUS connection
11822912Sartem  *  @param  message             Message
11832912Sartem  *  @return                     What to do with the message
11842912Sartem  */
11852912Sartem DBusHandlerResult
device_get_property(DBusConnection * connection,DBusMessage * message)11862912Sartem device_get_property (DBusConnection * connection, DBusMessage * message)
11872912Sartem {
11882912Sartem 	DBusMessage *reply;
11892912Sartem 	DBusMessageIter iter;
11902912Sartem 	DBusError error;
11912912Sartem 	HalDevice *d;
11922912Sartem 	const char *udi;
11932912Sartem 	char *key;
11942912Sartem 	int type;
11952912Sartem 	HalProperty *p;
11962912Sartem 
11972912Sartem 	udi = dbus_message_get_path (message);
11982912Sartem 
11992912Sartem 	HAL_TRACE (("entering, udi=%s", udi));
12002912Sartem 
12012912Sartem 	d = hal_device_store_find (hald_get_gdl (), udi);
12022912Sartem 	if (d == NULL)
12032912Sartem 		d = hal_device_store_find (hald_get_tdl (), udi);
12042912Sartem 
12052912Sartem 	if (d == NULL) {
12062912Sartem 		raise_no_such_device (connection, message, udi);
12072912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
12082912Sartem 	}
12092912Sartem 
12102912Sartem 	dbus_error_init (&error);
12112912Sartem 	if (!dbus_message_get_args (message, &error,
12122912Sartem 				    DBUS_TYPE_STRING, &key,
12132912Sartem 				    DBUS_TYPE_INVALID)) {
12142912Sartem 		raise_syntax (connection, message, "GetProperty");
12152912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
12162912Sartem 	}
12172912Sartem 
12182912Sartem 	p = hal_device_property_find (d, key);
12192912Sartem 	if (p == NULL) {
12202912Sartem 		raise_no_such_property (connection, message, udi, key);
12212912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
12222912Sartem 	}
12232912Sartem 
12242912Sartem 	reply = dbus_message_new_method_return (message);
12252912Sartem 	if (reply == NULL)
12262912Sartem 		DIE (("No memory"));
12272912Sartem 
12282912Sartem 	dbus_message_iter_init_append (reply, &iter);
12292912Sartem 
12302912Sartem 	type = hal_property_get_type (p);
12312912Sartem 	switch (type) {
12322912Sartem 	case HAL_PROPERTY_TYPE_STRING:
12332912Sartem 	{
12342912Sartem 		const char *s;
12352912Sartem 		s = hal_property_get_string (p);
12362912Sartem 		dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &s);
12372912Sartem 		break;
12382912Sartem 	}
12392912Sartem 	case HAL_PROPERTY_TYPE_INT32:
12402912Sartem 	{
12412912Sartem 		dbus_int32_t i;
12422912Sartem 		i = hal_property_get_int (p);
12432912Sartem 		dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &i);
12442912Sartem 		break;
12452912Sartem 	}
12462912Sartem 	case HAL_PROPERTY_TYPE_UINT64:
12472912Sartem 	{
12482912Sartem 		dbus_uint64_t ul;
12492912Sartem 		ul = hal_property_get_uint64 (p);
12502912Sartem 		dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT64, &ul);
12512912Sartem 		break;
12522912Sartem 	}
12532912Sartem 	case HAL_PROPERTY_TYPE_DOUBLE:
12542912Sartem 	{
12552912Sartem 		double d;
12562912Sartem 		d = hal_property_get_double (p);
12572912Sartem 		dbus_message_iter_append_basic (&iter, DBUS_TYPE_DOUBLE, &d);
12582912Sartem 		break;
12592912Sartem 	}
12602912Sartem 	case HAL_PROPERTY_TYPE_BOOLEAN:
12612912Sartem 	{
12622912Sartem 		dbus_bool_t b;
12632912Sartem 		b = hal_property_get_bool (p);
12642912Sartem 		dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &b);
12652912Sartem 		break;
12662912Sartem 	}
12672912Sartem 	case HAL_PROPERTY_TYPE_STRLIST:
12682912Sartem 	{
12692912Sartem 		GSList *l;
12702912Sartem 		DBusMessageIter iter_array;
12712912Sartem 
12722912Sartem 		dbus_message_iter_open_container (&iter,
12732912Sartem 						  DBUS_TYPE_ARRAY,
12742912Sartem 						  DBUS_TYPE_STRING_AS_STRING,
12752912Sartem 						  &iter_array);
12762912Sartem 
12772912Sartem 		for (l = hal_property_get_strlist (p); l != NULL; l = g_slist_next (l)) {
12782912Sartem 			dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_STRING, &(l->data));
12792912Sartem 		}
12802912Sartem 
12812912Sartem 		dbus_message_iter_close_container (&iter, &iter_array);
12822912Sartem 	}
12832912Sartem 		break;
12842912Sartem 
12852912Sartem 	default:
12862912Sartem 		HAL_WARNING (("Unknown property type %d", type));
12872912Sartem 		break;
12882912Sartem 	}
12892912Sartem 
12902912Sartem 	if (!dbus_connection_send (connection, reply, NULL))
12912912Sartem 		DIE (("No memory"));
12922912Sartem 
12932912Sartem 	dbus_message_unref (reply);
12942912Sartem 
12952912Sartem 	return DBUS_HANDLER_RESULT_HANDLED;
12962912Sartem }
12972912Sartem 
12982912Sartem 
12992912Sartem /** Get the type of a property on a device.
13002912Sartem  *
13012912Sartem  *  <pre>
13022912Sartem  *  int Device.GetPropertyType(string key)
13032912Sartem  *
13042912Sartem  *    raises org.freedesktop.Hal.NoSuchDevice,
13052912Sartem  *           org.freedesktop.Hal.NoSuchProperty
13062912Sartem  *  </pre>
13072912Sartem  *
13082912Sartem  *  @param  connection          D-BUS connection
13092912Sartem  *  @param  message             Message
13102912Sartem  *  @return                     What to do with the message
13112912Sartem  */
13122912Sartem DBusHandlerResult
device_get_property_type(DBusConnection * connection,DBusMessage * message)13132912Sartem device_get_property_type (DBusConnection * connection,
13142912Sartem 			  DBusMessage * message)
13152912Sartem {
13162912Sartem 	DBusMessage *reply;
13172912Sartem 	DBusMessageIter iter;
13182912Sartem 	DBusError error;
13192912Sartem 	HalDevice *d;
13202912Sartem 	const char *udi;
13212912Sartem 	char *key;
13222912Sartem 	HalProperty *p;
13232912Sartem 	dbus_int32_t i;
13242912Sartem 
13252912Sartem 	udi = dbus_message_get_path (message);
13262912Sartem 
13272912Sartem 	HAL_TRACE (("entering, udi=%s", udi));
13282912Sartem 
13292912Sartem 	d = hal_device_store_find (hald_get_gdl (), udi);
13302912Sartem 	if (d == NULL)
13312912Sartem 		d = hal_device_store_find (hald_get_tdl (), udi);
13322912Sartem 
13332912Sartem 	if (d == NULL) {
13342912Sartem 		raise_no_such_device (connection, message, udi);
13352912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
13362912Sartem 	}
13372912Sartem 
13382912Sartem 	dbus_error_init (&error);
13392912Sartem 	if (!dbus_message_get_args (message, &error,
13402912Sartem 				    DBUS_TYPE_STRING, &key,
13412912Sartem 				    DBUS_TYPE_INVALID)) {
13422912Sartem 		raise_syntax (connection, message, "GetPropertyType");
13432912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
13442912Sartem 	}
13452912Sartem 
13462912Sartem 	p = hal_device_property_find (d, key);
13472912Sartem 	if (p == NULL) {
13482912Sartem 		raise_no_such_property (connection, message, udi, key);
13492912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
13502912Sartem 	}
13512912Sartem 
13522912Sartem 	reply = dbus_message_new_method_return (message);
13532912Sartem 	if (reply == NULL)
13542912Sartem 		DIE (("No memory"));
13552912Sartem 
13562912Sartem 	i = hal_property_get_type (p);
13572912Sartem 	dbus_message_iter_init_append (reply, &iter);
13582912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &i);
13592912Sartem 
13602912Sartem 	if (!dbus_connection_send (connection, reply, NULL))
13612912Sartem 		DIE (("No memory"));
13622912Sartem 
13632912Sartem 	dbus_message_unref (reply);
13642912Sartem 
13652912Sartem 	return DBUS_HANDLER_RESULT_HANDLED;
13662912Sartem }
13672912Sartem 
13682912Sartem /** Set a property on a device.
13692912Sartem  *
13702912Sartem  *  <pre>
13712912Sartem  *  void Device.SetProperty(string key, any value)
13722912Sartem  *  void Device.SetPropertyString(string key, string value)
13732912Sartem  *  void Device.SetPropertyInteger(string key, int value)
13742912Sartem  *  void Device.SetPropertyBoolean(string key, bool value)
13752912Sartem  *  void Device.SetPropertyDouble(string key, double value)
13762912Sartem  *
13772912Sartem  *    raises org.freedesktop.Hal.NoSuchDevice,
13782912Sartem  *           org.freedesktop.Hal.NoSuchProperty
13792912Sartem  *           org.freedesktop.Hal.TypeMismatch
13802912Sartem  *  </pre>
13812912Sartem  *
13822912Sartem  *  @param  connection          D-BUS connection
13832912Sartem  *  @param  message             Message
13842912Sartem  *  @return                     What to do with the message
13852912Sartem  */
13862912Sartem DBusHandlerResult
device_set_property(DBusConnection * connection,DBusMessage * message,dbus_bool_t local_interface)13872912Sartem device_set_property (DBusConnection * connection, DBusMessage * message, dbus_bool_t local_interface)
13882912Sartem {
13892912Sartem 	const char *udi;
13902912Sartem 	char *key;
13912912Sartem 	int type;
13922912Sartem 	dbus_bool_t rc;
13932912Sartem 	HalDevice *device;
13942912Sartem 	DBusMessageIter iter;
13952912Sartem 	DBusMessage *reply;
13962912Sartem 
13972912Sartem 	HAL_TRACE (("entering"));
13982912Sartem 
13992912Sartem 	udi = dbus_message_get_path (message);
14002912Sartem 
14012912Sartem 	dbus_message_iter_init (message, &iter);
14022912Sartem 	type = dbus_message_iter_get_arg_type (&iter);
14032912Sartem 	if (type != DBUS_TYPE_STRING) {
14042912Sartem 		raise_syntax (connection, message, "SetProperty");
14052912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
14062912Sartem 	}
14072912Sartem 	dbus_message_iter_get_basic (&iter, &key);
14082912Sartem 
14092912Sartem 	if (!local_interface && !sender_has_privileges (connection, message)) {
14102912Sartem 		raise_permission_denied (connection, message, "SetProperty: not privileged");
14112912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
14122912Sartem 	}
14132912Sartem 
14142912Sartem 	HAL_DEBUG (("udi=%s, key=%s", udi, key));
14152912Sartem 
14162912Sartem 	device = hal_device_store_find (hald_get_gdl (), udi);
14172912Sartem 	if (device == NULL)
14182912Sartem 		device = hal_device_store_find (hald_get_tdl (), udi);
14192912Sartem 
14202912Sartem 	if (device == NULL) {
14212912Sartem 		raise_no_such_device (connection, message, udi);
14222912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
14232912Sartem 	}
14242912Sartem 	dbus_message_iter_next (&iter);
14252912Sartem 
14262912Sartem 	/** @todo check permissions of the sender vs property to be modified */
14272912Sartem 
14282912Sartem 	type = dbus_message_iter_get_arg_type (&iter);
14292912Sartem 	rc = FALSE;
14302912Sartem 
14312912Sartem 	switch (type) {
14322912Sartem 	case DBUS_TYPE_STRING:
14332912Sartem 	{
14342912Sartem 		const char *v;
14352912Sartem 		dbus_message_iter_get_basic (&iter, &v);
14362912Sartem 		rc = hal_device_property_set_string (device, key, v);
14372912Sartem 		break;
14382912Sartem 	}
14392912Sartem 	case DBUS_TYPE_INT32:
14402912Sartem 	{
14412912Sartem 		dbus_int32_t v;
14422912Sartem 		dbus_message_iter_get_basic (&iter, &v);
14432912Sartem 		rc = hal_device_property_set_int (device, key, v);
14442912Sartem 		break;
14452912Sartem 	}
14462912Sartem 	case DBUS_TYPE_UINT64:
14472912Sartem 	{
14482912Sartem 		dbus_uint64_t v;
14492912Sartem 		dbus_message_iter_get_basic (&iter, &v);
14502912Sartem 		rc = hal_device_property_set_uint64 (device, key, v);
14512912Sartem 		break;
14522912Sartem 	}
14532912Sartem 	case DBUS_TYPE_DOUBLE:
14542912Sartem 	{
14552912Sartem 		double v;
14562912Sartem 		dbus_message_iter_get_basic (&iter, &v);
14572912Sartem 		rc = hal_device_property_set_double (device, key, v);
14582912Sartem 		break;
14592912Sartem 	}
14602912Sartem 	case DBUS_TYPE_BOOLEAN:
14612912Sartem 	{
14622912Sartem 		dbus_bool_t v;
14632912Sartem 		dbus_message_iter_get_basic (&iter, &v);
14642912Sartem 		rc = hal_device_property_set_bool (device, key, v);
14652912Sartem 		break;
14662912Sartem 	}
14672912Sartem 	default:
14682912Sartem 		HAL_WARNING (("Unsupported property type %d", type));
14692912Sartem 		break;
14702912Sartem 	}
14712912Sartem 
14722912Sartem 	if (!rc) {
14732912Sartem 		raise_property_type_error (connection, message, udi, key);
14742912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
14752912Sartem 	}
14762912Sartem 
14772912Sartem 	reply = dbus_message_new_method_return (message);
14782912Sartem 	if (reply == NULL)
14792912Sartem 		DIE (("No memory"));
14802912Sartem 
14812912Sartem 	if (!dbus_connection_send (connection, reply, NULL))
14822912Sartem 		DIE (("No memory"));
14832912Sartem 
14842912Sartem 	dbus_message_unref (reply);
14852912Sartem 	return DBUS_HANDLER_RESULT_HANDLED;
14862912Sartem }
14872912Sartem 
14882912Sartem /** This function is used to modify the Capabilities property. The reason
14892912Sartem  *  for having a dedicated function is that the HAL daemon will broadcast
14902912Sartem  *  a signal on the Manager interface to tell applications that the device
14912912Sartem  *  have got a new capability.
14922912Sartem  *
14932912Sartem  *  This is useful as capabilities can be merged after the device is created.
14942912Sartem  *  One example of this is networking cards under Linux 2.6; the net.ethernet
14952912Sartem  *  capability is not merged when the device is initially found by looking in
14962912Sartem  *  /sys/devices; it is merged when the /sys/classes tree is searched.
14972912Sartem  *
14982912Sartem  *  Note that the signal is emitted every time this method is invoked even
14992912Sartem  *  though the capability already existed. This is useful in the above
15002912Sartem  *  scenario when the PCI class says ethernet networking card but we yet
15012912Sartem  *  don't have enough information to fill in the net.* and net.ethernet.*
15022912Sartem  *  fields since this only happens when we visit the /sys/classes tree.
15032912Sartem  *
15042912Sartem  *  <pre>
15052912Sartem  *  void Device.AddCapability(string capability)
15062912Sartem  *
15072912Sartem  *    raises org.freedesktop.Hal.NoSuchDevice,
15082912Sartem  *    raises org.freedesktop.Hal.PermissionDenied,
15092912Sartem  *  </pre>
15102912Sartem  *
15112912Sartem  *  @param  connection          D-BUS connection
15122912Sartem  *  @param  message             Message
15132912Sartem  *  @return                     What to do with the message
15142912Sartem  */
15152912Sartem DBusHandlerResult
device_add_capability(DBusConnection * connection,DBusMessage * message,dbus_bool_t local_interface)15162912Sartem device_add_capability (DBusConnection * connection, DBusMessage * message, dbus_bool_t local_interface)
15172912Sartem {
15182912Sartem 	const char *udi;
15192912Sartem 	const char *capability;
15202912Sartem 	HalDevice *d;
15212912Sartem 	DBusMessage *reply;
15222912Sartem 	DBusError error;
15232912Sartem 
15242912Sartem 	HAL_TRACE (("entering"));
15252912Sartem 
15262912Sartem 	if (!local_interface && !sender_has_privileges (connection, message)) {
15272912Sartem 		raise_permission_denied (connection, message, "AddCapability: not privileged");
15282912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
15292912Sartem 	}
15302912Sartem 
15312912Sartem 	udi = dbus_message_get_path (message);
15322912Sartem 
15332912Sartem 	d = hal_device_store_find (hald_get_gdl (), udi);
15342912Sartem 	if (d == NULL)
15352912Sartem 		d = hal_device_store_find (hald_get_tdl (), udi);
15362912Sartem 
15372912Sartem 	if (d == NULL) {
15382912Sartem 		raise_no_such_device (connection, message, udi);
15392912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
15402912Sartem 	}
15412912Sartem 
15422912Sartem 	dbus_error_init (&error);
15432912Sartem 	if (!dbus_message_get_args (message, &error,
15442912Sartem 				    DBUS_TYPE_STRING, &capability,
15452912Sartem 				    DBUS_TYPE_INVALID)) {
15462912Sartem 		raise_syntax (connection, message, "AddCapability");
15472912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
15482912Sartem 	}
15492912Sartem 
15502912Sartem 
15512912Sartem 	hal_device_add_capability (d, capability);
15522912Sartem 
15532912Sartem 	reply = dbus_message_new_method_return (message);
15542912Sartem 	if (reply == NULL)
15552912Sartem 		DIE (("No memory"));
15562912Sartem 
15572912Sartem 	if (!dbus_connection_send (connection, reply, NULL))
15582912Sartem 		DIE (("No memory"));
15592912Sartem 
15602912Sartem 	dbus_message_unref (reply);
15612912Sartem 	return DBUS_HANDLER_RESULT_HANDLED;
15622912Sartem }
15632912Sartem 
15642912Sartem 
15652912Sartem /* TODO: docs */
15662912Sartem static DBusHandlerResult
device_string_list_append_prepend(DBusConnection * connection,DBusMessage * message,dbus_bool_t do_prepend)15672912Sartem device_string_list_append_prepend (DBusConnection * connection, DBusMessage * message, dbus_bool_t do_prepend)
15682912Sartem {
15692912Sartem 	const char *udi;
15702912Sartem 	const char *key;
15712912Sartem 	const char *value;
15722912Sartem 	HalDevice *d;
15732912Sartem 	DBusMessage *reply;
15742912Sartem 	DBusError error;
15752912Sartem 	gboolean ret;
15762912Sartem 
15772912Sartem 	HAL_TRACE (("entering"));
15782912Sartem 
15792912Sartem 	udi = dbus_message_get_path (message);
15802912Sartem 
15812912Sartem 	d = hal_device_store_find (hald_get_gdl (), udi);
15822912Sartem 	if (d == NULL)
15832912Sartem 		d = hal_device_store_find (hald_get_tdl (), udi);
15842912Sartem 
15852912Sartem 	if (d == NULL) {
15862912Sartem 		raise_no_such_device (connection, message, udi);
15872912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
15882912Sartem 	}
15892912Sartem 
15902912Sartem 	dbus_error_init (&error);
15912912Sartem 	if (!dbus_message_get_args (message, &error,
15922912Sartem 				    DBUS_TYPE_STRING, &key,
15932912Sartem 				    DBUS_TYPE_STRING, &value,
15942912Sartem 				    DBUS_TYPE_INVALID)) {
15952912Sartem 		raise_syntax (connection, message, do_prepend ? "StringListPrepend" : "StringListAppend");
15962912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
15972912Sartem 	}
15982912Sartem 
15992912Sartem 	if (do_prepend)
16002912Sartem 		ret = hal_device_property_strlist_prepend (d, key, value);
16012912Sartem 	else
16022912Sartem 		ret = hal_device_property_strlist_append (d, key, value);
16032912Sartem 	if (!ret) {
16042912Sartem 		raise_property_type_error (connection, message, udi, key);
16052912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
16062912Sartem 	}
16072912Sartem 
16082912Sartem 	reply = dbus_message_new_method_return (message);
16092912Sartem 	if (reply == NULL)
16102912Sartem 		DIE (("No memory"));
16112912Sartem 
16122912Sartem 	if (!dbus_connection_send (connection, reply, NULL))
16132912Sartem 		DIE (("No memory"));
16142912Sartem 
16152912Sartem 	dbus_message_unref (reply);
16162912Sartem 	return DBUS_HANDLER_RESULT_HANDLED;
16172912Sartem }
16182912Sartem 
16192912Sartem /* TODO: docs */
16202912Sartem static DBusHandlerResult
device_string_list_remove(DBusConnection * connection,DBusMessage * message)16212912Sartem device_string_list_remove (DBusConnection * connection, DBusMessage * message)
16222912Sartem {
16232912Sartem 	const char *udi;
16242912Sartem 	const char *key;
16252912Sartem 	const char *value;
16262912Sartem 	HalDevice *d;
16272912Sartem 	DBusMessage *reply;
16282912Sartem 	DBusError error;
16292912Sartem 	gboolean ret;
16302912Sartem 
16312912Sartem 	HAL_TRACE (("entering"));
16322912Sartem 
16332912Sartem 	udi = dbus_message_get_path (message);
16342912Sartem 
16352912Sartem 	d = hal_device_store_find (hald_get_gdl (), udi);
16362912Sartem 	if (d == NULL)
16372912Sartem 		d = hal_device_store_find (hald_get_tdl (), udi);
16382912Sartem 
16392912Sartem 	if (d == NULL) {
16402912Sartem 		raise_no_such_device (connection, message, udi);
16412912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
16422912Sartem 	}
16432912Sartem 
16442912Sartem 	dbus_error_init (&error);
16452912Sartem 	if (!dbus_message_get_args (message, &error,
16462912Sartem 				    DBUS_TYPE_STRING, &key,
16472912Sartem 				    DBUS_TYPE_STRING, &value,
16482912Sartem 				    DBUS_TYPE_INVALID)) {
16492912Sartem 		raise_syntax (connection, message, "StringListRemove");
16502912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
16512912Sartem 	}
16522912Sartem 
16532912Sartem 	ret = hal_device_property_strlist_remove (d, key, value);
16542912Sartem 	if (!ret) {
16552912Sartem 		raise_property_type_error (connection, message, udi, key);
16562912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
16572912Sartem 	}
16582912Sartem 
16592912Sartem 	reply = dbus_message_new_method_return (message);
16602912Sartem 	if (reply == NULL)
16612912Sartem 		DIE (("No memory"));
16622912Sartem 
16632912Sartem 	if (!dbus_connection_send (connection, reply, NULL))
16642912Sartem 		DIE (("No memory"));
16652912Sartem 
16662912Sartem 	dbus_message_unref (reply);
16672912Sartem 	return DBUS_HANDLER_RESULT_HANDLED;
16682912Sartem }
16692912Sartem 
16702912Sartem 
16712912Sartem 
16722912Sartem /** Remove a property on a device.
16732912Sartem  *
16742912Sartem  *  <pre>
16752912Sartem  *  void Device.RemoveProperty(string key)
16762912Sartem  *
16772912Sartem  *    raises org.freedesktop.Hal.NoSuchDevice,
16782912Sartem  *           org.freedesktop.Hal.NoSuchProperty
16792912Sartem  *           org.freedesktop.Hal.PermissionDenied
16802912Sartem  *  </pre>
16812912Sartem  *
16822912Sartem  *  @param  connection          D-BUS connection
16832912Sartem  *  @param  message             Message
16842912Sartem  *  @return                     What to do with the message
16852912Sartem  */
16862912Sartem DBusHandlerResult
device_remove_property(DBusConnection * connection,DBusMessage * message,dbus_bool_t local_interface)16872912Sartem device_remove_property (DBusConnection * connection, DBusMessage * message, dbus_bool_t local_interface)
16882912Sartem {
16892912Sartem 	const char *udi;
16902912Sartem 	char *key;
16912912Sartem 	HalDevice *d;
16922912Sartem 	DBusMessage *reply;
16932912Sartem 	DBusError error;
16942912Sartem 
16952912Sartem 	HAL_TRACE (("entering"));
16962912Sartem 
16972912Sartem 	udi = dbus_message_get_path (message);
16982912Sartem 
16992912Sartem 	if (!local_interface && !sender_has_privileges (connection, message)) {
17002912Sartem 		raise_permission_denied (connection, message, "RemoveProperty: not privileged");
17012912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
17022912Sartem 	}
17032912Sartem 
17042912Sartem 	d = hal_device_store_find (hald_get_gdl (), udi);
17052912Sartem 	if (d == NULL)
17062912Sartem 		d = hal_device_store_find (hald_get_tdl (), udi);
17072912Sartem 
17082912Sartem 	if (d == NULL) {
17092912Sartem 		raise_no_such_device (connection, message, udi);
17102912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
17112912Sartem 	}
17122912Sartem 
17132912Sartem 	dbus_error_init (&error);
17142912Sartem 	if (!dbus_message_get_args (message, &error,
17152912Sartem 				    DBUS_TYPE_STRING, &key,
17162912Sartem 				    DBUS_TYPE_INVALID)) {
17172912Sartem 		raise_syntax (connection, message, "RemoveProperty");
17182912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
17192912Sartem 	}
17202912Sartem 
17212912Sartem 	if (!hal_device_property_remove (d, key)) {
17222912Sartem 		raise_no_such_property (connection, message, udi, key);
17232912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
17242912Sartem 	}
17252912Sartem 
17262912Sartem 
17272912Sartem 	reply = dbus_message_new_method_return (message);
17282912Sartem 	if (reply == NULL)
17292912Sartem 		DIE (("No memory"));
17302912Sartem 
17312912Sartem 	if (!dbus_connection_send (connection, reply, NULL))
17322912Sartem 		DIE (("No memory"));
17332912Sartem 
17342912Sartem 	dbus_message_unref (reply);
17352912Sartem 	return DBUS_HANDLER_RESULT_HANDLED;
17362912Sartem }
17372912Sartem 
17382912Sartem 
17392912Sartem /** Determine if a property exists
17402912Sartem  *
17412912Sartem  *  <pre>
17422912Sartem  *  bool Device.PropertyExists(string key)
17432912Sartem  *
17442912Sartem  *    raises org.freedesktop.Hal.NoSuchDevice,
17452912Sartem  *  </pre>
17462912Sartem  *
17472912Sartem  *  @param  connection          D-BUS connection
17482912Sartem  *  @param  message             Message
17492912Sartem  *  @return                     What to do with the message
17502912Sartem  */
17512912Sartem DBusHandlerResult
device_property_exists(DBusConnection * connection,DBusMessage * message)17522912Sartem device_property_exists (DBusConnection * connection, DBusMessage * message)
17532912Sartem {
17542912Sartem 	const char *udi;
17552912Sartem 	char *key;
17562912Sartem 	HalDevice *d;
17572912Sartem 	DBusMessage *reply;
17582912Sartem 	DBusError error;
17592912Sartem 	DBusMessageIter iter;
17602912Sartem 	dbus_bool_t b;
17612912Sartem 
17622912Sartem 	HAL_TRACE (("entering"));
17632912Sartem 
17642912Sartem 	udi = dbus_message_get_path (message);
17652912Sartem 
17662912Sartem 	d = hal_device_store_find (hald_get_gdl (), udi);
17672912Sartem 	if (d == NULL)
17682912Sartem 		d = hal_device_store_find (hald_get_tdl (), udi);
17692912Sartem 
17702912Sartem 	if (d == NULL) {
17712912Sartem 		raise_no_such_device (connection, message, udi);
17722912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
17732912Sartem 	}
17742912Sartem 
17752912Sartem 	dbus_error_init (&error);
17762912Sartem 	if (!dbus_message_get_args (message, &error,
17772912Sartem 				    DBUS_TYPE_STRING, &key,
17782912Sartem 				    DBUS_TYPE_INVALID)) {
17792912Sartem 		raise_syntax (connection, message, "RemoveProperty");
17802912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
17812912Sartem 	}
17822912Sartem 
17832912Sartem 	reply = dbus_message_new_method_return (message);
17842912Sartem 	if (reply == NULL)
17852912Sartem 		DIE (("No memory"));
17862912Sartem 
17872912Sartem 	b =  hal_device_has_property (d, key);
17882912Sartem 	dbus_message_iter_init_append (reply, &iter);
17892912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &b);
17902912Sartem 
17912912Sartem 	if (!dbus_connection_send (connection, reply, NULL))
17922912Sartem 		DIE (("No memory"));
17932912Sartem 
17942912Sartem 	dbus_message_unref (reply);
17952912Sartem 	return DBUS_HANDLER_RESULT_HANDLED;
17962912Sartem }
17972912Sartem 
17982912Sartem 
17992912Sartem /** Determine if a device has a capability
18002912Sartem  *
18012912Sartem  *  <pre>
18022912Sartem  *  bool Device.QueryCapability(string capability_name)
18032912Sartem  *
18042912Sartem  *    raises org.freedesktop.Hal.NoSuchDevice,
18052912Sartem  *  </pre>
18062912Sartem  *
18072912Sartem  *  @param  connection          D-BUS connection
18082912Sartem  *  @param  message             Message
18092912Sartem  *  @return                     What to do with the message
18102912Sartem  */
18112912Sartem DBusHandlerResult
device_query_capability(DBusConnection * connection,DBusMessage * message)18122912Sartem device_query_capability (DBusConnection * connection,
18132912Sartem 			 DBusMessage * message)
18142912Sartem {
18152912Sartem 	dbus_bool_t rc;
18162912Sartem 	const char *udi;
18172912Sartem 	GSList *caps;
18182912Sartem 	char *capability;
18192912Sartem 	HalDevice *d;
18202912Sartem 	DBusMessage *reply;
18212912Sartem 	DBusError error;
18222912Sartem 	DBusMessageIter iter;
18232912Sartem 
18242912Sartem 	HAL_TRACE (("entering"));
18252912Sartem 
18262912Sartem 	udi = dbus_message_get_path (message);
18272912Sartem 
18282912Sartem 	d = hal_device_store_find (hald_get_gdl (), udi);
18292912Sartem 	if (d == NULL)
18302912Sartem 		d = hal_device_store_find (hald_get_tdl (), udi);
18312912Sartem 
18322912Sartem 	if (d == NULL) {
18332912Sartem 		raise_no_such_device (connection, message, udi);
18342912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
18352912Sartem 	}
18362912Sartem 
18372912Sartem 	dbus_error_init (&error);
18382912Sartem 	if (!dbus_message_get_args (message, &error,
18392912Sartem 				    DBUS_TYPE_STRING, &capability,
18402912Sartem 				    DBUS_TYPE_INVALID)) {
18412912Sartem 		raise_syntax (connection, message, "QueryCapability");
18422912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
18432912Sartem 	}
18442912Sartem 
18452912Sartem 	reply = dbus_message_new_method_return (message);
18462912Sartem 	if (reply == NULL)
18472912Sartem 		DIE (("No memory"));
18482912Sartem 
18492912Sartem 	rc = FALSE;
18502912Sartem 	caps = hal_device_property_get_strlist (d, "info.capabilities");
18512912Sartem 	if (caps != NULL) {
18522912Sartem 		GSList *iter;
18532912Sartem 
18542912Sartem 		for (iter = caps; iter != NULL; iter=g_slist_next(iter)) {
18552912Sartem 			if (strcmp (iter->data, capability) == 0) {
18562912Sartem 				rc = TRUE;
18572912Sartem 				break;
18582912Sartem 			}
18592912Sartem 		}
18602912Sartem 	}
18612912Sartem 
18622912Sartem 	dbus_message_iter_init_append (reply, &iter);
18632912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &rc);
18642912Sartem 
18652912Sartem 	if (!dbus_connection_send (connection, reply, NULL))
18662912Sartem 		DIE (("No memory"));
18672912Sartem 
18682912Sartem 	dbus_message_unref (reply);
18692912Sartem 	return DBUS_HANDLER_RESULT_HANDLED;
18702912Sartem }
18712912Sartem 
18722912Sartem static GHashTable *services_with_locks = NULL;
18732912Sartem 
18742912Sartem /** Grab an advisory lock on a device.
18752912Sartem  *
18762912Sartem  *  <pre>
18772912Sartem  *  bool Device.Lock(string reason)
18782912Sartem  *
18792912Sartem  *    raises org.freedesktop.Hal.NoSuchDevice,
18802912Sartem  *           org.freedesktop.Hal.DeviceAlreadyLocked
18812912Sartem  *  </pre>
18822912Sartem  *
18832912Sartem  *  @param  connection          D-BUS connection
18842912Sartem  *  @param  message             Message
18852912Sartem  *  @return                     What to do with the message
18862912Sartem  */
18872912Sartem DBusHandlerResult
device_lock(DBusConnection * connection,DBusMessage * message)18882912Sartem device_lock (DBusConnection * connection,
18892912Sartem 	     DBusMessage * message)
18902912Sartem {
18912912Sartem 	const char *udi;
18922912Sartem 	HalDevice *d;
18932912Sartem 	DBusMessage *reply;
18942912Sartem 	dbus_bool_t already_locked;
18952912Sartem 	DBusError error;
18962912Sartem 	char *reason;
18972912Sartem 	const char *sender;
18982912Sartem 
18992912Sartem 	HAL_TRACE (("entering"));
19002912Sartem 
19012912Sartem 	udi = dbus_message_get_path (message);
19022912Sartem 
19032912Sartem 	d = hal_device_store_find (hald_get_gdl (), udi);
19042912Sartem 	if (d == NULL)
19052912Sartem 		d = hal_device_store_find (hald_get_tdl (), udi);
19062912Sartem 
19072912Sartem 	if (d == NULL) {
19082912Sartem 		raise_no_such_device (connection, message, udi);
19092912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
19102912Sartem 	}
19112912Sartem 
19122912Sartem 	already_locked = hal_device_property_get_bool (d, "info.locked");
19132912Sartem 
19142912Sartem 	if (already_locked) {
19152912Sartem 		raise_device_already_locked (connection, message, d);
19162912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
19172912Sartem 	}
19182912Sartem 
19192912Sartem 	dbus_error_init (&error);
19202912Sartem 	if (!dbus_message_get_args (message, &error,
19212912Sartem 				    DBUS_TYPE_STRING, &reason,
19222912Sartem 				    DBUS_TYPE_INVALID)) {
19232912Sartem 		raise_syntax (connection, message, "Lock");
19242912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
19252912Sartem 	}
19262912Sartem 
19272912Sartem 	reply = dbus_message_new_method_return (message);
19282912Sartem 	if (reply == NULL)
19292912Sartem 		DIE (("No memory"));
19302912Sartem 
19312912Sartem 	sender = dbus_message_get_sender (message);
19322912Sartem 
19332912Sartem 	hal_device_property_set_bool (d, "info.locked", TRUE);
19342912Sartem 	hal_device_property_set_string (d, "info.locked.reason", reason);
19352912Sartem 	hal_device_property_set_string (d, "info.locked.dbus_name",
19362912Sartem 					sender);
19372912Sartem 
19382912Sartem 	if (services_with_locks == NULL) {
19392912Sartem 		services_with_locks =
19402912Sartem 			g_hash_table_new_full (g_str_hash,
19412912Sartem 					       g_str_equal,
19422912Sartem 					       g_free,
19432912Sartem 					       g_object_unref);
19442912Sartem 	}
19452912Sartem 
19462912Sartem 	g_hash_table_insert (services_with_locks, g_strdup (sender),
19472912Sartem 			     g_object_ref (d));
19482912Sartem 
19492912Sartem 	if (!dbus_connection_send (connection, reply, NULL))
19502912Sartem 		DIE (("No memory"));
19512912Sartem 
19522912Sartem 	dbus_message_unref (reply);
19532912Sartem 	return DBUS_HANDLER_RESULT_HANDLED;
19542912Sartem }
19552912Sartem 
19562912Sartem /** Release an advisory lock on a device.
19572912Sartem  *
19582912Sartem  *  <pre>
19592912Sartem  *  bool Device.Unlock()
19602912Sartem  *
19612912Sartem  *    raises org.freedesktop.Hal.NoSuchDevice,
19622912Sartem  *           org.freedesktop.Hal.DeviceNotLocked,
19632912Sartem  *           org.freedesktop.Hal.PermissionDenied
19642912Sartem  *  </pre>
19652912Sartem  *
19662912Sartem  *  @param  connection          D-BUS connection
19672912Sartem  *  @param  message             Message
19682912Sartem  *  @return                     What to do with the message
19692912Sartem  */
19702912Sartem DBusHandlerResult
device_unlock(DBusConnection * connection,DBusMessage * message)19712912Sartem device_unlock (DBusConnection * connection,
19722912Sartem 	       DBusMessage * message)
19732912Sartem {
19742912Sartem 	dbus_bool_t rc;
19752912Sartem 	const char *udi;
19762912Sartem 	HalDevice *d;
19772912Sartem 	DBusMessage *reply;
19782912Sartem 	DBusError error;
19792912Sartem 	const char *sender;
19802912Sartem 
19812912Sartem 	HAL_TRACE (("entering"));
19822912Sartem 
19832912Sartem 	udi = dbus_message_get_path (message);
19842912Sartem 
19852912Sartem 	d = hal_device_store_find (hald_get_gdl (), udi);
19862912Sartem 	if (d == NULL)
19872912Sartem 		d = hal_device_store_find (hald_get_tdl (), udi);
19882912Sartem 
19892912Sartem 	if (d == NULL) {
19902912Sartem 		raise_no_such_device (connection, message, udi);
19912912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
19922912Sartem 	}
19932912Sartem 
19942912Sartem 	dbus_error_init (&error);
19952912Sartem 	if (!dbus_message_get_args (message, &error,
19962912Sartem 				    DBUS_TYPE_INVALID)) {
19972912Sartem 		raise_syntax (connection, message, "Unlock");
19982912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
19992912Sartem 	}
20002912Sartem 
20012912Sartem 	reply = dbus_message_new_method_return (message);
20022912Sartem 	if (reply == NULL)
20032912Sartem 		DIE (("No memory"));
20042912Sartem 
20052912Sartem 	rc = hal_device_property_get_bool (d, "info.locked");
20062912Sartem 
20072912Sartem 	if (!rc) {
20082912Sartem 		raise_device_not_locked (connection, message, d);
20092912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
20102912Sartem 	}
20112912Sartem 
20122912Sartem 	sender = dbus_message_get_sender (message);
20132912Sartem 
20142912Sartem 	if (strcmp (sender, hal_device_property_get_string (
20152912Sartem 			    d, "info.locked.dbus_name")) != 0) {
20162912Sartem 		char *reason;
20172912Sartem 
20182912Sartem 		reason = g_strdup_printf ("Service '%s' does not own the "
20192912Sartem 					  "lock on %s", sender,
20202912Sartem 					  hal_device_get_udi (d));
20212912Sartem 
20222912Sartem 		raise_permission_denied (connection, message, reason);
20232912Sartem 
20242912Sartem 		g_free (reason);
20252912Sartem 
20262912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
20272912Sartem 	}
20282912Sartem 
20292912Sartem 	if (g_hash_table_lookup (services_with_locks, sender))
20302912Sartem 		g_hash_table_remove (services_with_locks, sender);
20312912Sartem 	else {
20322912Sartem 		HAL_WARNING (("Service '%s' was not in the list of services "
20332912Sartem 			      "with locks!", sender));
20342912Sartem 	}
20352912Sartem 
20362912Sartem 	hal_device_property_remove (d, "info.locked");
20372912Sartem 	hal_device_property_remove (d, "info.locked.reason");
20382912Sartem 	hal_device_property_remove (d, "info.locked.dbus_name");
20392912Sartem 
20402912Sartem 	/* FIXME?  Pointless? */
20412912Sartem 	if (!dbus_connection_send (connection, reply, NULL))
20422912Sartem 		DIE (("No memory"));
20432912Sartem 
20442912Sartem 	dbus_message_unref (reply);
20452912Sartem 	return DBUS_HANDLER_RESULT_HANDLED;
20462912Sartem }
20472912Sartem 
20482912Sartem static GHashTable *services_with_claims = NULL;
20492912Sartem 
20502912Sartem /** Claim a branch.
20512912Sartem  *
20522912Sartem  *  <pre>
20532912Sartem  *  bool Manager.ClaimBranch(string udi, string claim_service)
20542912Sartem  *  </pre>
20552912Sartem  *
20562912Sartem  *  @param  connection          D-BUS connection
20572912Sartem  *  @param  message             Message
20582912Sartem  *  @return                     What to do with the message
20592912Sartem  */
20602912Sartem DBusHandlerResult
manager_claim_branch(DBusConnection * connection,DBusMessage * message)20612912Sartem manager_claim_branch (DBusConnection * connection, DBusMessage * message)
20622912Sartem {
20632912Sartem 	DBusMessage *reply;
20642912Sartem 	DBusMessageIter iter;
20652912Sartem 	DBusError error;
20662912Sartem 	HalDevice *d;
20672912Sartem 	const char *udi;
20682912Sartem 	const char *claim_service;
20692912Sartem 	const char *sender;
20702912Sartem 	dbus_bool_t already_claimed;
20712912Sartem 	unsigned long uid;
20722912Sartem 
20732912Sartem 	dbus_error_init (&error);
20742912Sartem 	if (!dbus_message_get_args (message, &error,
20752912Sartem 				    DBUS_TYPE_STRING, &udi,
20762912Sartem 				    DBUS_TYPE_STRING, &claim_service,
20772912Sartem 				    DBUS_TYPE_INVALID)) {
20782912Sartem 		raise_syntax (connection, message, "Manager.ClaimBranch");
20792912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
20802912Sartem 	}
20812912Sartem 
20822912Sartem 	HAL_TRACE (("entering, udi=%s", udi));
20832912Sartem 
20842912Sartem 	d = hal_device_store_find (hald_get_gdl (), udi);
20852912Sartem 
20862912Sartem 	if (d == NULL) {
20872912Sartem 		raise_no_such_device (connection, message, udi);
20882912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
20892912Sartem 	}
20902912Sartem 
20912912Sartem 	already_claimed = hal_device_property_get_bool (d, "info.claimed");
20922912Sartem 	if (already_claimed) {
20932912Sartem 		raise_branch_already_claimed (connection, message, d);
20942912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
20952912Sartem 	}
20962912Sartem 
20972912Sartem 	reply = dbus_message_new_method_return (message);
20982912Sartem 	if (reply == NULL)
20992912Sartem 		DIE (("No memory"));
21002912Sartem 
21012912Sartem 	sender = dbus_message_get_sender (message);
21022912Sartem 
21032912Sartem 	dbus_error_init (&error);
21042912Sartem 	uid = dbus_bus_get_unix_user (connection, sender, &error);
21052912Sartem 	if (uid == (unsigned long) -1 || dbus_error_is_set (&error)) {
21062912Sartem 		HAL_WARNING (("Could not get uid for connection: %s %s", error.name, error.message));
21072912Sartem 		dbus_error_free (&error);
21082912Sartem 		dbus_message_unref (reply);
21092912Sartem 		raise_no_such_device (connection, message, udi);
21102912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
21112912Sartem 	}
21122912Sartem 
21132912Sartem 	hal_util_branch_claim (hald_get_gdl (), d, TRUE, claim_service, uid);
21142912Sartem 	hal_device_property_set_string (d, "info.claimed.dbus_name", sender);
21152912Sartem 
21162912Sartem 	if (services_with_claims == NULL) {
21172912Sartem 		services_with_claims =
21182912Sartem 			g_hash_table_new_full (g_str_hash,
21192912Sartem 					       g_str_equal,
21202912Sartem 					       g_free,
21212912Sartem 					       g_object_unref);
21222912Sartem 	}
21232912Sartem 
21242912Sartem 	g_hash_table_insert (services_with_claims, g_strdup (sender),
21252912Sartem 			     g_object_ref (d));
21262912Sartem 
21272912Sartem 	if (!dbus_connection_send (connection, reply, NULL))
21282912Sartem 		DIE (("No memory"));
21292912Sartem 
21302912Sartem 	dbus_message_unref (reply);
21312912Sartem 	return DBUS_HANDLER_RESULT_HANDLED;
21322912Sartem }
21332912Sartem 
21342912Sartem /** Unclaim a branch.
21352912Sartem  *
21362912Sartem  *  <pre>
21372912Sartem  *  bool Manager.UnclaimBranch(string udi)
21382912Sartem  *  </pre>
21392912Sartem  *
21402912Sartem  *  @param  connection          D-BUS connection
21412912Sartem  *  @param  message             Message
21422912Sartem  *  @return                     What to do with the message
21432912Sartem  */
21442912Sartem DBusHandlerResult
manager_unclaim_branch(DBusConnection * connection,DBusMessage * message)21452912Sartem manager_unclaim_branch (DBusConnection * connection, DBusMessage * message)
21462912Sartem {
21472912Sartem 	DBusMessage *reply;
21482912Sartem 	DBusMessageIter iter;
21492912Sartem 	DBusError error;
21502912Sartem 	HalDevice *d;
21512912Sartem 	const char *udi;
21522912Sartem 	const char *claim_service;
21532912Sartem 	const char *sender;
21542912Sartem 	dbus_bool_t already_claimed;
21552912Sartem 
21562912Sartem 	dbus_error_init (&error);
21572912Sartem 	if (!dbus_message_get_args (message, &error,
21582912Sartem 				    DBUS_TYPE_STRING, &udi,
21592912Sartem 				    DBUS_TYPE_INVALID)) {
21602912Sartem 		raise_syntax (connection, message, "Manager.UnclaimBranch");
21612912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
21622912Sartem 	}
21632912Sartem 
21642912Sartem 	HAL_TRACE (("entering, udi=%s", udi));
21652912Sartem 
21662912Sartem 	d = hal_device_store_find (hald_get_gdl (), udi);
21672912Sartem 
21682912Sartem 	if (d == NULL) {
21692912Sartem 		raise_no_such_device (connection, message, udi);
21702912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
21712912Sartem 	}
21722912Sartem 
21732912Sartem 	already_claimed = hal_device_property_get_bool (d, "info.claimed");
21742912Sartem 	if (!already_claimed) {
21752912Sartem 		raise_branch_not_claimed (connection, message, d);
21762912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
21772912Sartem 	}
21782912Sartem 
21792912Sartem 	reply = dbus_message_new_method_return (message);
21802912Sartem 	if (reply == NULL)
21812912Sartem 		DIE (("No memory"));
21822912Sartem 
21832912Sartem 	if (strcmp (sender, hal_device_property_get_string (
21842912Sartem 			    d, "info.claimed.dbus_name")) != 0) {
21852912Sartem 		char *reason;
21862912Sartem 
21872912Sartem 		reason = g_strdup_printf ("Service '%s' does not own the "
21882912Sartem 					  "claim on %s", sender,
21892912Sartem 					  hal_device_get_udi (d));
21902912Sartem 
21912912Sartem 		raise_permission_denied (connection, message, reason);
21922912Sartem 
21932912Sartem 		g_free (reason);
21942912Sartem 
21952912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
21962912Sartem 	}
21972912Sartem 
21982912Sartem 	if (g_hash_table_lookup (services_with_claims, sender))
21992912Sartem 		g_hash_table_remove (services_with_claims, sender);
22002912Sartem 	else {
22012912Sartem 		HAL_WARNING (("Service '%s' was not in the list of services "
22022912Sartem 			      "with claims!", sender));
22032912Sartem 	}
22042912Sartem 
22052912Sartem 	hal_util_branch_claim (hald_get_gdl (), d, FALSE, NULL, 0);
22062912Sartem 	hal_device_property_remove (d, "info.claimed.dbus_name");
22072912Sartem 
22082912Sartem 	if (!dbus_connection_send (connection, reply, NULL))
22092912Sartem 		DIE (("No memory"));
22102912Sartem 
22112912Sartem 	dbus_message_unref (reply);
22122912Sartem 	return DBUS_HANDLER_RESULT_HANDLED;
22132912Sartem }
22142912Sartem 
22152912Sartem 
22162912Sartem /** Counter for atomic updating */
22172912Sartem static int atomic_count = 0;
22182912Sartem 
22192912Sartem /** Number of updates pending */
22202912Sartem static int num_pending_updates = 0;
22212912Sartem 
22222912Sartem /** Structure for queing updates */
22232912Sartem typedef struct PendingUpdate_s {
22242912Sartem 	char *udi;                    /**< udi of device */
22252912Sartem 	char *key;                    /**< key of property; free when done */
22262912Sartem 	dbus_bool_t removed;          /**< true iff property was removed */
22272912Sartem 	dbus_bool_t added;            /**< true iff property was added */
22282912Sartem 	struct PendingUpdate_s *next; /**< next update or #NULL */
22292912Sartem } PendingUpdate;
22302912Sartem 
22312912Sartem static PendingUpdate *pending_updates_head = NULL;
22322912Sartem 
22332912Sartem /** Begin an atomic update - this is useful for updating several properties
22342912Sartem  *  in one go.
22352912Sartem  *
22362912Sartem  *  Note that an atomic update is recursive - use with caution!
22372912Sartem  */
22382912Sartem void
device_property_atomic_update_begin(void)22392912Sartem device_property_atomic_update_begin (void)
22402912Sartem {
22412912Sartem 	atomic_count++;
22422912Sartem }
22432912Sartem 
22442912Sartem /** End an atomic update.
22452912Sartem  *
22462912Sartem  *  Note that an atomic update is recursive - use with caution!
22472912Sartem  */
22482912Sartem void
device_property_atomic_update_end(void)22492912Sartem device_property_atomic_update_end (void)
22502912Sartem {
22512912Sartem 	PendingUpdate *pu_iter = NULL;
22522912Sartem 	PendingUpdate *pu_iter_next = NULL;
22532912Sartem 	PendingUpdate *pu_iter2 = NULL;
22542912Sartem 
22552912Sartem 	--atomic_count;
22562912Sartem 
22572912Sartem 	if (atomic_count < 0) {
22582912Sartem 		HAL_WARNING (("*** atomic_count = %d < 0 !!", atomic_count));
22592912Sartem 		atomic_count = 0;
22602912Sartem 	}
22612912Sartem 
22622912Sartem 	if (atomic_count == 0 && num_pending_updates > 0) {
22632912Sartem 		DBusMessage *message;
22642912Sartem 		DBusMessageIter iter;
22652912Sartem 		DBusMessageIter iter_array;
22662912Sartem 
22672912Sartem 		for (pu_iter = pending_updates_head;
22682912Sartem 		     pu_iter != NULL; pu_iter = pu_iter_next) {
22692912Sartem 			int num_updates_this;
22702912Sartem 
22712912Sartem 			pu_iter_next = pu_iter->next;
22722912Sartem 
22732912Sartem 			/* see if we've already processed this */
22742912Sartem 			if (pu_iter->udi == NULL)
22752912Sartem 				goto already_processed;
22762912Sartem 
22772912Sartem 			/* count number of updates for this device */
22782912Sartem 			num_updates_this = 0;
22792912Sartem 			for (pu_iter2 = pu_iter; pu_iter2 != NULL; pu_iter2 = pu_iter2->next) {
22802912Sartem 				if (strcmp (pu_iter2->udi, pu_iter->udi) == 0)
22812912Sartem 					num_updates_this++;
22822912Sartem 			}
22832912Sartem 
22842912Sartem 			/* prepare message */
22852912Sartem 			message = dbus_message_new_signal (pu_iter->udi,
22862912Sartem 							   "org.freedesktop.Hal.Device",
22872912Sartem 							   "PropertyModified");
22882912Sartem 			dbus_message_iter_init_append (message, &iter);
22892912Sartem 			dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32,
22902912Sartem 							&num_updates_this);
22912912Sartem 
22922912Sartem 			dbus_message_iter_open_container (&iter,
22932912Sartem 							  DBUS_TYPE_ARRAY,
22942912Sartem 							  DBUS_STRUCT_BEGIN_CHAR_AS_STRING
22952912Sartem 							  DBUS_TYPE_STRING_AS_STRING
22962912Sartem 							  DBUS_TYPE_BOOLEAN_AS_STRING
22972912Sartem 							  DBUS_TYPE_BOOLEAN_AS_STRING
22982912Sartem 							  DBUS_STRUCT_END_CHAR_AS_STRING,
22992912Sartem 							  &iter_array);
23002912Sartem 
23012912Sartem 			for (pu_iter2 = pu_iter; pu_iter2 != NULL;
23022912Sartem 			     pu_iter2 = pu_iter2->next) {
23032912Sartem 				if (strcmp (pu_iter2->udi, pu_iter->udi) == 0) {
23042912Sartem 					DBusMessageIter iter_struct;
23052912Sartem 					dbus_message_iter_open_container (&iter_array,
23062912Sartem 									  DBUS_TYPE_STRUCT,
23072912Sartem 									  NULL,
23082912Sartem 									  &iter_struct);
23092912Sartem 					dbus_message_iter_append_basic
23102912Sartem 					    (&iter_struct,
23112912Sartem 					     DBUS_TYPE_STRING,
23122912Sartem 					     &(pu_iter2->key));
23132912Sartem 					dbus_message_iter_append_basic
23142912Sartem 					    (&iter_struct,
23152912Sartem 					     DBUS_TYPE_BOOLEAN,
23162912Sartem 					     &(pu_iter2->removed));
23172912Sartem 					dbus_message_iter_append_basic
23182912Sartem 					    (&iter_struct,
23192912Sartem 					     DBUS_TYPE_BOOLEAN,
23202912Sartem 					     &(pu_iter2->added));
23212912Sartem 
23222912Sartem 					dbus_message_iter_close_container (&iter_array, &iter_struct);
23232912Sartem 
23242912Sartem 					/* signal this is already processed */
23252912Sartem 					g_free (pu_iter2->key);
23262912Sartem 					if (pu_iter2 != pu_iter) {
23272912Sartem 						g_free (pu_iter2->udi);
23282912Sartem 						pu_iter2->udi = NULL;
23292912Sartem 					}
23302912Sartem 				}
23312912Sartem 			}
23322912Sartem 
23332912Sartem 			g_free (pu_iter->udi);
23342912Sartem 			dbus_message_iter_close_container (&iter, &iter_array);
23352912Sartem 
23362912Sartem 			if (dbus_connection != NULL) {
23372912Sartem 				if (!dbus_connection_send (dbus_connection, message, NULL))
23382912Sartem 					DIE (("error broadcasting message"));
23392912Sartem 			}
23402912Sartem 
23412912Sartem 			dbus_message_unref (message);
23422912Sartem 
23432912Sartem 		already_processed:
23442912Sartem 			g_free (pu_iter);
23452912Sartem 
23462912Sartem 		} /* for all updates */
23472912Sartem 
23482912Sartem 		num_pending_updates = 0;
23492912Sartem 		pending_updates_head = NULL;
23502912Sartem 	}
23512912Sartem }
23522912Sartem 
23532912Sartem 
23542912Sartem 
23552912Sartem void
device_send_signal_property_modified(HalDevice * device,const char * key,dbus_bool_t added,dbus_bool_t removed)23562912Sartem device_send_signal_property_modified (HalDevice *device, const char *key,
23572912Sartem 				      dbus_bool_t added, dbus_bool_t removed)
23582912Sartem {
23592912Sartem 	const char *udi = hal_device_get_udi (device);
23602912Sartem 	DBusMessage *message;
23612912Sartem 	DBusMessageIter iter;
23622912Sartem 
23632912Sartem /*
23642912Sartem     HAL_INFO(("Entering, udi=%s, key=%s, in_gdl=%s, removed=%s added=%s",
23652912Sartem               device->udi, key,
23662912Sartem               in_gdl ? "true" : "false",
23672912Sartem               removed ? "true" : "false",
23682912Sartem               added ? "true" : "false"));
23692912Sartem */
23702912Sartem 
23712912Sartem 	if (atomic_count > 0) {
23722912Sartem 		PendingUpdate *pu;
23732912Sartem 
23742912Sartem 		pu = g_new0 (PendingUpdate, 1);
23752912Sartem 		pu->udi = g_strdup (udi);
23762912Sartem 		pu->key = g_strdup (key);
23772912Sartem 		pu->removed = removed;
23782912Sartem 		pu->added = added;
23792912Sartem 		pu->next = pending_updates_head;
23802912Sartem 
23812912Sartem 		pending_updates_head = pu;
23822912Sartem 		num_pending_updates++;
23832912Sartem 	} else {
23842912Sartem 		dbus_int32_t i;
23852912Sartem 		DBusMessageIter iter_struct;
23862912Sartem 		DBusMessageIter iter_array;
23872912Sartem 
23882912Sartem 		if (dbus_connection == NULL)
23892912Sartem 			goto out;
23902912Sartem 
23912912Sartem 		message = dbus_message_new_signal (udi,
23922912Sartem 						  "org.freedesktop.Hal.Device",
23932912Sartem 						   "PropertyModified");
23942912Sartem 
23952912Sartem 		dbus_message_iter_init_append (message, &iter);
23962912Sartem 		i = 1;
23972912Sartem 		dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &i);
23982912Sartem 
23992912Sartem 		dbus_message_iter_open_container (&iter,
24002912Sartem 						  DBUS_TYPE_ARRAY,
24012912Sartem 						  DBUS_STRUCT_BEGIN_CHAR_AS_STRING
24022912Sartem 						  DBUS_TYPE_STRING_AS_STRING
24032912Sartem 						  DBUS_TYPE_BOOLEAN_AS_STRING
24042912Sartem 						  DBUS_TYPE_BOOLEAN_AS_STRING
24052912Sartem 						  DBUS_STRUCT_END_CHAR_AS_STRING,
24062912Sartem 						  &iter_array);
24072912Sartem 
24082912Sartem 		dbus_message_iter_open_container (&iter_array,
24092912Sartem 						  DBUS_TYPE_STRUCT,
24102912Sartem 						  NULL,
24112912Sartem 						  &iter_struct);
24122912Sartem 
24132912Sartem 		dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &key);
24142912Sartem 		dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_BOOLEAN, &removed);
24152912Sartem 		dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_BOOLEAN, &added);
24162912Sartem 
24172912Sartem 		dbus_message_iter_close_container (&iter_array, &iter_struct);
24182912Sartem 		dbus_message_iter_close_container (&iter, &iter_array);
24192912Sartem 
24202912Sartem 		if (!dbus_connection_send (dbus_connection, message, NULL))
24212912Sartem 			DIE (("error broadcasting message"));
24222912Sartem 
24232912Sartem 		dbus_message_unref (message);
24242912Sartem 	}
24252912Sartem out:
24262912Sartem 	;
24272912Sartem }
24282912Sartem 
24292912Sartem /** Emits a condition on a device; the device has to be in the GDL for
24302912Sartem  *  this function to have effect.
24312912Sartem  *
24322912Sartem  *  Is intended for non-continuous events on the device like
24332912Sartem  *  ProcesserOverheating, BlockDeviceGotDevice, e.g. conditions that
24342912Sartem  *  are exceptional and may not be inferred by looking at properties
24352912Sartem  *  (though some may).
24362912Sartem  *
24372912Sartem  *  This function accepts a number of parameters that are passed along
24382912Sartem  *  in the D-BUS message. The recipient is supposed to extract the parameters
24392912Sartem  *  himself, by looking at the HAL specification.
24402912Sartem  *
24412912Sartem  * @param  udi                  The UDI for this device
24422912Sartem  * @param  condition_name       Name of condition
24432912Sartem  * @param  first_arg_type       Type of the first argument
24442912Sartem  * @param  ...                  value of first argument, list of additional
24452912Sartem  *                              type-value pairs. Must be terminated with
24462912Sartem  *                              DBUS_TYPE_INVALID
24472912Sartem  */
24482912Sartem void
device_send_signal_condition(HalDevice * device,const char * condition_name,const char * condition_details)24492912Sartem device_send_signal_condition (HalDevice *device, const char *condition_name, const char *condition_details)
24502912Sartem {
24512912Sartem 	const char *udi = hal_device_get_udi (device);
24522912Sartem 	DBusMessage *message;
24532912Sartem 	DBusMessageIter iter;
24542912Sartem 
24552912Sartem 	if (dbus_connection == NULL)
24562912Sartem 		goto out;
24572912Sartem 
24582912Sartem 	message = dbus_message_new_signal (udi,
24592912Sartem 					   "org.freedesktop.Hal.Device",
24602912Sartem 					   "Condition");
24612912Sartem 	dbus_message_iter_init_append (message, &iter);
24622912Sartem 	dbus_message_iter_append_basic (&iter,
24632912Sartem 					DBUS_TYPE_STRING,
24642912Sartem 					&condition_name);
24652912Sartem 	dbus_message_iter_append_basic (&iter,
24662912Sartem 					DBUS_TYPE_STRING,
24672912Sartem 					&condition_details);
24682912Sartem 
24692912Sartem 	if (!dbus_connection_send (dbus_connection, message, NULL))
24702912Sartem 		DIE (("error broadcasting message"));
24712912Sartem 
24722912Sartem 	dbus_message_unref (message);
24732912Sartem out:
24742912Sartem 	return;
24752912Sartem }
24762912Sartem 
24772912Sartem 
24782912Sartem 
24792912Sartem static gboolean
reinit_dbus(gpointer user_data)24802912Sartem reinit_dbus (gpointer user_data)
24812912Sartem {
24822912Sartem 	HAL_INFO (("entering!"));
24832912Sartem 	if (hald_dbus_init ())
24842912Sartem 		return FALSE;
24852912Sartem 	else
24862912Sartem 		return TRUE;
24872912Sartem }
24882912Sartem 
24892912Sartem static void
service_deleted(DBusMessage * message)24902912Sartem service_deleted (DBusMessage *message)
24912912Sartem {
24922912Sartem 	char *old_service_name;
24932912Sartem 	char *new_service_name;
24942912Sartem 	HalDevice *d;
24952912Sartem 
24962912Sartem 	if (!dbus_message_get_args (message, NULL,
24972912Sartem 				    DBUS_TYPE_STRING, &old_service_name,
24982912Sartem 				    DBUS_TYPE_STRING, &new_service_name,
24992912Sartem 				    DBUS_TYPE_INVALID)) {
25002912Sartem 		HAL_ERROR (("Invalid NameOwnerChanged signal from bus!"));
25012912Sartem 		return;
25022912Sartem 	}
25032912Sartem 
25042912Sartem 	if (services_with_locks != NULL) {
25052912Sartem 		d = g_hash_table_lookup (services_with_locks, new_service_name);
25062912Sartem 
25072912Sartem 		if (d != NULL) {
25082912Sartem 			hal_device_property_remove (d, "info.locked");
25092912Sartem 			hal_device_property_remove (d, "info.locked.reason");
25102912Sartem 			hal_device_property_remove (d, "info.locked.dbus_name");
25112912Sartem 
25122912Sartem 			g_hash_table_remove (services_with_locks, new_service_name);
25132912Sartem 		}
25142912Sartem 	}
25152912Sartem 
25162912Sartem 	if (services_with_claims != NULL) {
25172912Sartem 		d = g_hash_table_lookup (services_with_claims, new_service_name);
25182912Sartem 
25192912Sartem 		if (d != NULL) {
25202912Sartem 			hal_util_branch_claim (hald_get_gdl (), d, FALSE, NULL, 0);
25212912Sartem 			hal_device_property_remove (d, "info.claimed.dbus_name");
25222912Sartem 
25232912Sartem 			g_hash_table_remove (services_with_claims, new_service_name);
25242912Sartem 		}
25252912Sartem 	}
25262912Sartem }
25272912Sartem 
25282912Sartem static DBusHandlerResult
device_rescan(DBusConnection * connection,DBusMessage * message,dbus_bool_t local_interface)25292912Sartem device_rescan (DBusConnection * connection, DBusMessage * message, dbus_bool_t local_interface)
25302912Sartem {
25312912Sartem 	const char *udi;
25322912Sartem 	HalDevice *device;
25332912Sartem 	DBusMessage *reply;
25342912Sartem 	DBusMessageIter iter;
25352912Sartem 	gboolean res;
25362912Sartem 
25372912Sartem 	HAL_INFO (("entering, local_interface=%d", local_interface));
25382912Sartem 
25392912Sartem 	udi = dbus_message_get_path (message);
25402912Sartem 
25412912Sartem 	if (!local_interface && !sender_has_privileges (connection, message)) {
25422912Sartem 		raise_permission_denied (connection, message, "Rescan: not privileged");
25432912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
25442912Sartem 	}
25452912Sartem 
25462912Sartem 	HAL_DEBUG (("udi=%s", udi));
25472912Sartem 
25482912Sartem 	device = hal_device_store_find (hald_get_gdl (), udi);
25492912Sartem 	if (device == NULL)
25502912Sartem 		device = hal_device_store_find (hald_get_tdl (), udi);
25512912Sartem 
25522912Sartem 	if (device == NULL) {
25532912Sartem 		raise_no_such_device (connection, message, udi);
25542912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
25552912Sartem 	}
25562912Sartem 
25572912Sartem 	res = osspec_device_rescan (device);
25582912Sartem 
25592912Sartem 	reply = dbus_message_new_method_return (message);
25602912Sartem 	if (reply == NULL)
25612912Sartem 		DIE (("No memory"));
25622912Sartem 	dbus_message_iter_init_append (reply, &iter);
25632912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &res);
25642912Sartem 
25652912Sartem 	if (!dbus_connection_send (connection, reply, NULL))
25662912Sartem 		DIE (("No memory"));
25672912Sartem 
25682912Sartem 	dbus_message_unref (reply);
25692912Sartem 	return DBUS_HANDLER_RESULT_HANDLED;
25702912Sartem }
25712912Sartem 
25722912Sartem static DBusHandlerResult
device_reprobe(DBusConnection * connection,DBusMessage * message,dbus_bool_t local_interface)25732912Sartem device_reprobe (DBusConnection * connection, DBusMessage * message, dbus_bool_t local_interface)
25742912Sartem {
25752912Sartem 	const char *udi;
25762912Sartem 	HalDevice *device;
25772912Sartem 	DBusMessageIter iter;
25782912Sartem 	DBusMessage *reply;
25792912Sartem 	gboolean res;
25802912Sartem 
25812912Sartem 	HAL_TRACE (("entering"));
25822912Sartem 
25832912Sartem 	udi = dbus_message_get_path (message);
25842912Sartem 
25852912Sartem 	if (!local_interface && !sender_has_privileges (connection, message)) {
25862912Sartem 		raise_permission_denied (connection, message, "Reprobe: not privileged");
25872912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
25882912Sartem 	}
25892912Sartem 
25902912Sartem 	HAL_DEBUG (("udi=%s", udi));
25912912Sartem 
25922912Sartem 	device = hal_device_store_find (hald_get_gdl (), udi);
25932912Sartem 	if (device == NULL)
25942912Sartem 		device = hal_device_store_find (hald_get_tdl (), udi);
25952912Sartem 
25962912Sartem 	if (device == NULL) {
25972912Sartem 		raise_no_such_device (connection, message, udi);
25982912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
25992912Sartem 	}
26002912Sartem 
26012912Sartem 	res = osspec_device_reprobe (device);
26022912Sartem 
26032912Sartem 	reply = dbus_message_new_method_return (message);
26042912Sartem 	if (reply == NULL)
26052912Sartem 		DIE (("No memory"));
26062912Sartem 	dbus_message_iter_init_append (reply, &iter);
26072912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &res);
26082912Sartem 
26092912Sartem 	if (!dbus_connection_send (connection, reply, NULL))
26102912Sartem 		DIE (("No memory"));
26112912Sartem 
26122912Sartem 	dbus_message_unref (reply);
26132912Sartem 	return DBUS_HANDLER_RESULT_HANDLED;
26142912Sartem }
26152912Sartem 
26162912Sartem 
26172912Sartem static DBusHandlerResult
device_emit_condition(DBusConnection * connection,DBusMessage * message,dbus_bool_t local_interface)26182912Sartem device_emit_condition (DBusConnection * connection, DBusMessage * message, dbus_bool_t local_interface)
26192912Sartem {
26202912Sartem 	const char *udi;
26212912Sartem 	HalDevice *device;
26222912Sartem 	DBusMessageIter iter;
26232912Sartem 	DBusMessage *reply;
26242912Sartem 	DBusError error;
26252912Sartem 	const char *condition_name;
26262912Sartem 	const char *condition_details;
26272912Sartem 	dbus_bool_t res;
26282912Sartem 
26292912Sartem 	HAL_TRACE (("entering"));
26302912Sartem 
26312912Sartem 	udi = dbus_message_get_path (message);
26322912Sartem 
26332912Sartem 	if (!local_interface) {
26342912Sartem 		raise_permission_denied (connection, message, "EmitCondition: only allowed for helpers");
26352912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
26362912Sartem 	}
26372912Sartem 
26382912Sartem 	HAL_DEBUG (("udi=%s", udi));
26392912Sartem 
26402912Sartem 	dbus_error_init (&error);
26412912Sartem 	if (!dbus_message_get_args (message, &error,
26422912Sartem 				    DBUS_TYPE_STRING, &condition_name,
26432912Sartem 				    DBUS_TYPE_STRING, &condition_details,
26442912Sartem 				    DBUS_TYPE_INVALID)) {
26452912Sartem 		raise_syntax (connection, message, "EmitCondition");
26462912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
26472912Sartem 	}
26482912Sartem 
26492912Sartem 
26502912Sartem 	device = hal_device_store_find (hald_get_gdl (), udi);
26512912Sartem 	if (device == NULL)
26522912Sartem 		device = hal_device_store_find (hald_get_tdl (), udi);
26532912Sartem 
26542912Sartem 	if (device == NULL) {
26552912Sartem 		raise_no_such_device (connection, message, udi);
26562912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
26572912Sartem 	}
26582912Sartem 
26592912Sartem 	device_send_signal_condition (device, condition_name, condition_details);
26602912Sartem 
26612912Sartem 	res = TRUE;
26622912Sartem 
26632912Sartem 	reply = dbus_message_new_method_return (message);
26642912Sartem 	if (reply == NULL)
26652912Sartem 		DIE (("No memory"));
26662912Sartem 	dbus_message_iter_init_append (reply, &iter);
26672912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &res);
26682912Sartem 
26692912Sartem 	if (!dbus_connection_send (connection, reply, NULL))
26702912Sartem 		DIE (("No memory"));
26712912Sartem 
26722912Sartem 	dbus_message_unref (reply);
26732912Sartem 	return DBUS_HANDLER_RESULT_HANDLED;
26742912Sartem }
26752912Sartem 
26762912Sartem typedef struct
26772912Sartem {
26782912Sartem 	DBusConnection  *connection;
26792912Sartem 	char            *interface_name;
26802912Sartem 	char            *introspection_xml;
26812912Sartem 	char            *udi;
26822912Sartem } HelperInterfaceHandler;
26832912Sartem 
26842912Sartem static GSList *helper_interface_handlers = NULL;
26852912Sartem 
26862912Sartem static DBusHandlerResult
device_claim_interface(DBusConnection * connection,DBusMessage * message,dbus_bool_t local_interface)26872912Sartem device_claim_interface (DBusConnection * connection, DBusMessage * message, dbus_bool_t local_interface)
26882912Sartem {
26892912Sartem 	const char *udi;
26902912Sartem 	HalDevice *device;
26912912Sartem 	DBusMessageIter iter;
26922912Sartem 	DBusMessage *reply;
26932912Sartem 	DBusError error;
26942912Sartem 	const char *interface_name;
26952912Sartem 	const char *introspection_xml;
26962912Sartem 	dbus_bool_t res;
26972912Sartem 
26982912Sartem 	HAL_TRACE (("entering"));
26992912Sartem 
27002912Sartem 	udi = dbus_message_get_path (message);
27012912Sartem 
27022912Sartem 	if (!local_interface) {
27032912Sartem 		raise_permission_denied (connection, message, "ClaimInterface: only allowed for helpers");
27042912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
27052912Sartem 	}
27062912Sartem 
27072912Sartem 	HAL_DEBUG (("udi=%s", udi));
27082912Sartem 
27092912Sartem 	dbus_error_init (&error);
27102912Sartem 	if (!dbus_message_get_args (message, &error,
27112912Sartem 				    DBUS_TYPE_STRING, &interface_name,
27122912Sartem 				    DBUS_TYPE_STRING, &introspection_xml,
27132912Sartem 				    DBUS_TYPE_INVALID)) {
27142912Sartem 		raise_syntax (connection, message, "ClaimInterface");
27152912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
27162912Sartem 	}
27172912Sartem 
27182912Sartem 	device = hal_device_store_find (hald_get_gdl (), udi);
27192912Sartem 	if (device == NULL)
27202912Sartem 		device = hal_device_store_find (hald_get_tdl (), udi);
27212912Sartem 
27222912Sartem 	if (device == NULL) {
27232912Sartem 		raise_no_such_device (connection, message, udi);
27242912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
27252912Sartem 	}
27262912Sartem 
27272912Sartem 	res = TRUE;
27282912Sartem 
27292912Sartem 	HAL_INFO (("Local connection 0x%x to handle interface '%s' on udi '%s'",
27302912Sartem 		   connection,
27312912Sartem 		   interface_name,
27322912Sartem 		   udi));
27332912Sartem 
27342912Sartem 	hal_device_property_strlist_add (device, "info.interfaces", interface_name);
27352912Sartem 
27362912Sartem 	HelperInterfaceHandler *hih = g_new0 (HelperInterfaceHandler, 1);
27372912Sartem 	hih->connection = connection;
27382912Sartem 	hih->interface_name = g_strdup (interface_name);
27392912Sartem 	hih->introspection_xml = g_strdup (introspection_xml);
27402912Sartem 	hih->udi = g_strdup (udi);
27412912Sartem 	helper_interface_handlers = g_slist_append (helper_interface_handlers, hih);
27422912Sartem 
27432912Sartem 
27442912Sartem 	reply = dbus_message_new_method_return (message);
27452912Sartem 	if (reply == NULL)
27462912Sartem 		DIE (("No memory"));
27472912Sartem 	dbus_message_iter_init_append (reply, &iter);
27482912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &res);
27492912Sartem 
27502912Sartem 	if (!dbus_connection_send (connection, reply, NULL))
27512912Sartem 		DIE (("No memory"));
27522912Sartem 
27532912Sartem 	dbus_message_unref (reply);
27542912Sartem 	return DBUS_HANDLER_RESULT_HANDLED;
27552912Sartem }
27562912Sartem 
27572912Sartem 
27582912Sartem 
27592912Sartem static DBusHandlerResult
addon_is_ready(DBusConnection * connection,DBusMessage * message,dbus_bool_t local_interface)27602912Sartem addon_is_ready (DBusConnection * connection, DBusMessage * message, dbus_bool_t local_interface)
27612912Sartem {
27622912Sartem 	const char *udi;
27632912Sartem 	HalDevice *device;
27642912Sartem 	DBusMessageIter iter;
27652912Sartem 	DBusMessage *reply;
27662912Sartem 	DBusError error;
27672912Sartem 	dbus_bool_t res;
27682912Sartem 
27692912Sartem 	HAL_TRACE (("entering"));
27702912Sartem 
27712912Sartem 	udi = dbus_message_get_path (message);
27722912Sartem 
27732912Sartem 	if (!local_interface) {
27742912Sartem 		raise_permission_denied (connection, message, "AddonIsReady: only allowed for helpers");
27752912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
27762912Sartem 	}
27772912Sartem 
27782912Sartem 	HAL_DEBUG (("udi=%s", udi));
27792912Sartem 
27802912Sartem 	dbus_error_init (&error);
27812912Sartem 	if (!dbus_message_get_args (message, &error,
27822912Sartem 				    DBUS_TYPE_INVALID)) {
27832912Sartem 		raise_syntax (connection, message, "AddonIsReady");
27842912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
27852912Sartem 	}
27862912Sartem 
27872912Sartem 	device = hal_device_store_find (hald_get_gdl (), udi);
27882912Sartem 	if (device == NULL)
27892912Sartem 		device = hal_device_store_find (hald_get_tdl (), udi);
27902912Sartem 
27912912Sartem 	if (device == NULL) {
27922912Sartem 		raise_no_such_device (connection, message, udi);
27932912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
27942912Sartem 	}
27952912Sartem 
27962912Sartem 	if (hal_device_inc_num_ready_addons (device)) {
27972912Sartem 		if (hal_device_are_all_addons_ready (device)) {
27982912Sartem 			manager_send_signal_device_added (device);
27992912Sartem 		}
28002912Sartem 	}
28012912Sartem 
28022912Sartem 	res = TRUE;
28032912Sartem 
28042912Sartem 	HAL_INFO (("AddonIsReady on udi '%s'", udi));
28052912Sartem 
28062912Sartem 	reply = dbus_message_new_method_return (message);
28072912Sartem 	if (reply == NULL)
28082912Sartem 		DIE (("No memory"));
28092912Sartem 	dbus_message_iter_init_append (reply, &iter);
28102912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &res);
28112912Sartem 
28122912Sartem 	if (!dbus_connection_send (connection, reply, NULL))
28132912Sartem 		DIE (("No memory"));
28142912Sartem 
28152912Sartem 	dbus_message_unref (reply);
28162912Sartem 	return DBUS_HANDLER_RESULT_HANDLED;
28172912Sartem }
28182912Sartem 
28192912Sartem 
28202912Sartem /*
28212912Sartem  * Create new device in tdl. Return temporary udi.
28222912Sartem  */
28232912Sartem DBusHandlerResult
manager_new_device(DBusConnection * connection,DBusMessage * message,dbus_bool_t local_interface)28242912Sartem manager_new_device (DBusConnection * connection, DBusMessage * message, dbus_bool_t local_interface)
28252912Sartem {
28262912Sartem 	DBusMessage *reply;
28272912Sartem 	DBusMessageIter iter;
28282912Sartem 	DBusError error;
28292912Sartem 	HalDevice *d;
28302912Sartem 	gchar *udi;
28312912Sartem 	int i;
28322912Sartem 	struct timeval tv;
28332912Sartem 
28342912Sartem 	dbus_error_init (&error);
28352912Sartem 
28362912Sartem 	if (!local_interface && !sender_has_privileges (connection, message)) {
28372912Sartem 		raise_permission_denied (connection, message, "NewDevice: not privileged");
28382912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
28392912Sartem 	}
28402912Sartem 
28412912Sartem 	reply = dbus_message_new_method_return (message);
28422912Sartem 	if (reply == NULL)
28432912Sartem 		DIE (("No memory"));
28442912Sartem 
28452912Sartem 	dbus_message_iter_init_append (reply, &iter);
28462912Sartem 	d = hal_device_new ();
28472912Sartem 
28482912Sartem 	gettimeofday(&tv, NULL);
28492912Sartem 	for (i = 0; i < 1000000 ; i++) {
28502912Sartem 		udi = g_strdup_printf ("/org/freedesktop/Hal/devices/tmp%05x", ((unsigned) tv.tv_usec & 0xfffff)) + i;
28512912Sartem 		if (!hal_device_store_find (hald_get_tdl (), udi)) break;
28522912Sartem 		g_free (udi);
28532912Sartem 		udi = NULL;
28542912Sartem 	}
28552912Sartem 
28562912Sartem 	if (!udi) {
28572912Sartem 		raise_error (connection, message, "org.freedesktop.Hal.NoSpace", "NewDevice: no space for device");
28582912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
28592912Sartem 	}
28602912Sartem 
28612912Sartem 	hal_device_set_udi (d, udi);
28622912Sartem 	hal_device_property_set_string (d, "info.udi", udi);
28632912Sartem 	hal_device_store_add (hald_get_tdl (), d);
28642912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &udi);
28652912Sartem 	g_free (udi);
28662912Sartem 
28672912Sartem 	if (!dbus_connection_send (connection, reply, NULL))
28682912Sartem 		DIE (("No memory"));
28692912Sartem 
28702912Sartem 	dbus_message_unref (reply);
28712912Sartem 
28722912Sartem 	return DBUS_HANDLER_RESULT_HANDLED;
28732912Sartem }
28742912Sartem 
28752912Sartem 
28762912Sartem /*
28772912Sartem  * Callout helper.
28782912Sartem  */
28792912Sartem static void
manager_remove_done(HalDevice * d,gpointer userdata1,gpointer userdata2)28802912Sartem manager_remove_done (HalDevice *d, gpointer userdata1, gpointer userdata2)
28812912Sartem {
28822912Sartem 	HAL_INFO (("Remove callouts completed udi=%s", d->udi));
28832912Sartem 
28842912Sartem 	if (!hal_device_store_remove (hald_get_gdl (), d)) {
28852912Sartem 		HAL_WARNING (("Error removing device"));
28862912Sartem 	}
28872912Sartem }
28882912Sartem 
28892912Sartem 
28902912Sartem /*
28912912Sartem  * Remove device. Looks in gdl and tdl.
28922912Sartem  */
28932912Sartem DBusHandlerResult
manager_remove(DBusConnection * connection,DBusMessage * message,dbus_bool_t local_interface)28942912Sartem manager_remove (DBusConnection * connection, DBusMessage * message, dbus_bool_t local_interface)
28952912Sartem {
28962912Sartem 	DBusMessage *reply;
28972912Sartem 	DBusMessageIter iter;
28982912Sartem 	DBusError error;
28992912Sartem 	HalDevice *d;
29002912Sartem 	char *udi;
29012912Sartem 	int in_tdl = 0;
29022912Sartem 
29032912Sartem 	dbus_error_init (&error);
29042912Sartem 
29052912Sartem 	if (!local_interface && !sender_has_privileges (connection, message)) {
29062912Sartem 		raise_permission_denied (connection, message, "Remove: not privileged");
29072912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
29082912Sartem 	}
29092912Sartem 
29102912Sartem 	if (!dbus_message_get_args (message, &error,
29112912Sartem 				    DBUS_TYPE_STRING, &udi,
29122912Sartem 				    DBUS_TYPE_INVALID)) {
29132912Sartem 		raise_syntax (connection, message, "Remove");
29142912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
29152912Sartem 	}
29162912Sartem 
29172912Sartem 	reply = dbus_message_new_method_return (message);
29182912Sartem 	if (reply == NULL)
29192912Sartem 		DIE (("No memory"));
29202912Sartem 
29212912Sartem 	dbus_message_iter_init_append (reply, &iter);
29222912Sartem 
29232912Sartem 	d = hal_device_store_find (hald_get_gdl (), udi);
29242912Sartem 	if (d == NULL) {
29252912Sartem 		hal_device_store_find (hald_get_tdl (), udi);
29262912Sartem 		in_tdl = 1;
29272912Sartem 	}
29282912Sartem 	if (d == NULL) {
29292912Sartem 		raise_no_such_device (connection, message, udi);
29302912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
29312912Sartem 	}
29322912Sartem 
29332912Sartem 	/* FIXME:
29342912Sartem 	 * run "info.callouts.remove" ?
29352912Sartem 	 * delete in gdl ?
29362912Sartem 	 * (auto) stop "info.addons" ?
29372912Sartem 	 */
29382912Sartem 
29392912Sartem 	if (!in_tdl) {
29402912Sartem 		hal_util_callout_device_remove (d, manager_remove_done, NULL, NULL);
29412912Sartem 	}
29422912Sartem 
29432912Sartem 	hal_device_store_remove (in_tdl ? hald_get_tdl () : hald_get_gdl (), d);
29442912Sartem 	g_object_unref (d);
29452912Sartem 
29462912Sartem 	if (!dbus_connection_send (connection, reply, NULL))
29472912Sartem 		DIE (("No memory"));
29482912Sartem 
29492912Sartem 	dbus_message_unref (reply);
29502912Sartem 
29512912Sartem 	return DBUS_HANDLER_RESULT_HANDLED;
29522912Sartem }
29532912Sartem 
29542912Sartem 
29552912Sartem /*
29562912Sartem  * Callout helper.
29572912Sartem  */
29582912Sartem static void
manager_commit_done(HalDevice * d,gpointer userdata1,gpointer userdata2)29592912Sartem manager_commit_done (HalDevice *d, gpointer userdata1, gpointer userdata2)
29602912Sartem {
29612912Sartem 	HAL_INFO (("Add callouts completed udi=%s", d->udi));
29622912Sartem }
29632912Sartem 
29642912Sartem /*
29652912Sartem  * Preprobing helper.
29662912Sartem  */
29672912Sartem static void
manager_commit_preprobing_done(HalDevice * d,gpointer userdata1,gpointer userdata2)29682912Sartem manager_commit_preprobing_done (HalDevice *d, gpointer userdata1, gpointer userdata2)
29692912Sartem {
29702912Sartem 	if (hal_device_property_get_bool (d, "info.ignore")) {
29712912Sartem 		/* Leave the device here with info.ignore==TRUE so we won't pick up children
29722912Sartem 		 * Also remove category and all capabilities
29732912Sartem 		 */
29742912Sartem 		hal_device_property_remove (d, "info.category");
29752912Sartem 		hal_device_property_remove (d, "info.capabilities");
29762912Sartem 		hal_device_property_set_string (d, "info.udi", "/org/freedesktop/Hal/devices/ignored-device");
29772912Sartem 		hal_device_property_set_string (d, "info.product", "Ignored Device");
29782912Sartem 
29792912Sartem 		HAL_INFO (("Preprobing merged info.ignore==TRUE"));
29802912Sartem 
29812912Sartem 		return;
29822912Sartem 	}
29832912Sartem 
29842912Sartem 	/* Merge properties from .fdi files */
29852912Sartem 	di_search_and_merge (d, DEVICE_INFO_TYPE_INFORMATION);
29862912Sartem 	di_search_and_merge (d, DEVICE_INFO_TYPE_POLICY);
29872912Sartem 
29882912Sartem 	hal_util_callout_device_add (d, manager_commit_done, NULL, NULL);
29892912Sartem }
29902912Sartem 
29912912Sartem 
29922912Sartem /*
29932912Sartem  * Move device from tdl to gdl. Runs helpers and callouts.
29942912Sartem  */
29952912Sartem DBusHandlerResult
manager_commit_to_gdl(DBusConnection * connection,DBusMessage * message,dbus_bool_t local_interface)29962912Sartem manager_commit_to_gdl (DBusConnection * connection, DBusMessage * message, dbus_bool_t local_interface)
29972912Sartem {
29982912Sartem 	DBusMessage *reply;
29992912Sartem 	DBusMessageIter iter;
30002912Sartem 	DBusError error;
30012912Sartem 	HalDevice *d;
30022912Sartem 	char udi[256], *udi0, *tmp_udi;
30032912Sartem 
30042912Sartem 	dbus_error_init (&error);
30052912Sartem 
30062912Sartem 	if (!local_interface && !sender_has_privileges (connection, message)) {
30072912Sartem 		raise_permission_denied (connection, message, "CommitToGdl: not privileged");
30082912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
30092912Sartem 	}
30102912Sartem 
30112912Sartem 	if (!dbus_message_get_args (message, &error,
30122912Sartem 				    DBUS_TYPE_STRING, &tmp_udi,
30132912Sartem 				    DBUS_TYPE_STRING, &udi0,
30142912Sartem 				    DBUS_TYPE_INVALID)) {
30152912Sartem 		raise_syntax (connection, message, "CommitToGdl");
30162912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
30172912Sartem 	}
30182912Sartem 
30192912Sartem 	reply = dbus_message_new_method_return (message);
30202912Sartem 	if (reply == NULL)
30212912Sartem 		DIE (("No memory"));
30222912Sartem 
30232912Sartem 	dbus_message_iter_init_append (reply, &iter);
30242912Sartem 
30252912Sartem 	/* look it up in tdl */
30262912Sartem 
30272912Sartem 	d = hal_device_store_find (hald_get_tdl (), tmp_udi);
30282912Sartem 	if (d == NULL) {
30292912Sartem 		raise_no_such_device (connection, message, tmp_udi);
30302912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
30312912Sartem 	}
30322912Sartem 
30332912Sartem 	/* sanity check & avoid races */
30342912Sartem 	hal_util_compute_udi (hald_get_gdl (), udi, sizeof udi, "%s", udi0);
30352912Sartem 
30362912Sartem 	if (hal_device_store_find (hald_get_gdl (), udi)) {
30372912Sartem 		/* loose it */
30382912Sartem 		hal_device_store_remove (hald_get_tdl (), d);
30392912Sartem 		g_object_unref (d);
30402912Sartem 		raise_error (connection, message, "org.freedesktop.Hal.DeviceExists", "CommitToGdl: Device exists: %s", udi);
30412912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
30422912Sartem 	}
30432912Sartem 
30442912Sartem 	/* set new udi */
30452912Sartem 	hal_device_property_remove (d, "info.udi");
30462912Sartem 	hal_device_set_udi (d, udi);
30472912Sartem 	hal_device_property_set_string (d, "info.udi", udi);
30482912Sartem 
30492912Sartem 	/* FIXME:
30502912Sartem 	 * 'RequireEnable' property?
30512912Sartem 	 * fdi "preprobe"?
30522912Sartem 	 * run "info.callouts.preprobe"?
30532912Sartem 	 * remove "info.ignore" devices?
30542912Sartem 	 * fdi "information"?
30552912Sartem 	 * fdi "policy"?
30562912Sartem 	 * run "info.callouts.add"?
30572912Sartem 	 * tdl -> gdl?
30582912Sartem 	 * (auto) start "info.addons"?
30592912Sartem 	 */
30602912Sartem 
30612912Sartem 	/* Process preprobe fdi files */
30622912Sartem 	di_search_and_merge (d, DEVICE_INFO_TYPE_PREPROBE);
30632912Sartem 	hal_util_callout_device_preprobe (d, manager_commit_preprobing_done, NULL, NULL);
30642912Sartem 
30652912Sartem 	/* move from tdl to gdl */
30662912Sartem 	hal_device_store_remove (hald_get_tdl (), d);
30672912Sartem 	hal_device_store_add (hald_get_gdl (), d);
30682912Sartem 
30692912Sartem 	if (!dbus_connection_send (connection, reply, NULL))
30702912Sartem 		DIE (("No memory"));
30712912Sartem 
30722912Sartem 	dbus_message_unref (reply);
30732912Sartem 
30742912Sartem 	return DBUS_HANDLER_RESULT_HANDLED;
30752912Sartem }
30762912Sartem 
30772912Sartem typedef struct {
30782912Sartem 	char *udi;
30792912Sartem 	char *execpath;
30802912Sartem 	char **extra_env;
30812912Sartem 	char *mstdin;
30822912Sartem 	char *member;
30832912Sartem 	char *interface;
30842912Sartem 	DBusMessage *message;
30852912Sartem 	DBusConnection *connection;
30862912Sartem } MethodInvocation;
30872912Sartem 
30882912Sartem static void
30892912Sartem hald_exec_method_cb (HalDevice *d, guint32 exit_type,
30902912Sartem 		     gint return_code, gchar **error,
30912912Sartem 		     gpointer data1, gpointer data2);
30922912Sartem 
30932912Sartem 
30942912Sartem static void
hald_exec_method_free_mi(MethodInvocation * mi)30952912Sartem hald_exec_method_free_mi (MethodInvocation *mi)
30962912Sartem {
30972912Sartem 	/* hald_runner_run_method() assumes ownership of mi->message.. so we don't free it here */
30982912Sartem 	g_free (mi->udi);
30992912Sartem 	g_free (mi->execpath);
31002912Sartem 	g_strfreev (mi->extra_env);
31012912Sartem 	g_free (mi->mstdin);
31022912Sartem 	g_free (mi->member);
31032912Sartem 	g_free (mi->interface);
31042912Sartem 	g_free (mi);
31052912Sartem }
31062912Sartem 
31072912Sartem /* returns FALSE if we don't actually invoke anything */
31082912Sartem static gboolean
hald_exec_method_do_invocation(MethodInvocation * mi)31092912Sartem hald_exec_method_do_invocation (MethodInvocation *mi)
31102912Sartem {
31112912Sartem 	gboolean ret;
31122912Sartem 	HalDevice *d;
31132912Sartem 
31142912Sartem 	ret = FALSE;
31152912Sartem 
31162912Sartem 	d = hal_device_store_find (hald_get_gdl (), mi->udi);
31172912Sartem 	if (d == NULL)
31182912Sartem 		d = hal_device_store_find (hald_get_tdl (), mi->udi);
31192912Sartem 
31202912Sartem 	if (d != NULL) {
31212912Sartem 		/* no timeout */
31222912Sartem 		hald_runner_run_method(d,
31232912Sartem 				       mi->execpath,
31242912Sartem 				       mi->extra_env,
31252912Sartem 				       mi->mstdin,
31262912Sartem 				       TRUE,
31272912Sartem 				       0,
31282912Sartem 				       hald_exec_method_cb,
31292912Sartem 				       (gpointer) mi->message,
31302912Sartem 				       (gpointer) mi->connection);
31312912Sartem 
31322912Sartem 		ret = TRUE;
31332912Sartem 	} else {
31342912Sartem 		HAL_WARNING (("In-queue method call on non-existant device"));
31352912Sartem 
31362912Sartem 		raise_no_such_device (mi->connection, mi->message, mi->udi);
31372912Sartem 	}
31382912Sartem 
31392912Sartem 	return ret;
31402912Sartem }
31412912Sartem 
31422912Sartem 
31432912Sartem static GHashTable *udi_to_method_queue = NULL;
31442912Sartem 
31452912Sartem 
31462912Sartem gboolean
device_is_executing_method(HalDevice * d,const char * interface_name,const char * method_name)31472912Sartem device_is_executing_method (HalDevice *d, const char *interface_name, const char *method_name)
31482912Sartem {
31492912Sartem 	gpointer origkey;
31502912Sartem 	gboolean ret;
31512912Sartem 	GList *queue;
31522912Sartem 
31532912Sartem 	ret = FALSE;
31542912Sartem 
31552912Sartem 	if (g_hash_table_lookup_extended (udi_to_method_queue, d->udi, &origkey, (gpointer) &queue)) {
31562912Sartem 
31572912Sartem 		if (queue != NULL) {
31582912Sartem 			MethodInvocation *mi;
31592912Sartem 			mi = (MethodInvocation *) queue->data;
31602912Sartem 			if ((strcmp (mi->interface, interface_name) == 0) &&
31612912Sartem 			    (strcmp (mi->member, method_name) == 0)) {
31622912Sartem 				ret = TRUE;
31632912Sartem 			}
31642912Sartem 		}
31652912Sartem 
31662912Sartem 		ret = TRUE;
31672912Sartem 	}
31682912Sartem 	return ret;
31692912Sartem }
31702912Sartem 
31712912Sartem static void
31722912Sartem hald_exec_method_process_queue (const char *udi);
31732912Sartem 
31742912Sartem static void
hald_exec_method_enqueue(MethodInvocation * mi)31752912Sartem hald_exec_method_enqueue (MethodInvocation *mi)
31762912Sartem {
31772912Sartem 	gpointer origkey;
31782912Sartem 	GList *queue;
31792912Sartem 
31802912Sartem 	if (udi_to_method_queue == NULL) {
31812912Sartem 		udi_to_method_queue = g_hash_table_new_full (g_str_hash,
31822912Sartem 							     g_str_equal,
31832912Sartem 							     g_free,
31842912Sartem 							     NULL);
31852912Sartem 	}
31862912Sartem 
31872912Sartem 	if (g_hash_table_lookup_extended (udi_to_method_queue, mi->udi, &origkey, (gpointer) &queue)) {
31882912Sartem 		HAL_INFO (("enqueue"));
31892912Sartem 		queue = g_list_append (queue, mi);
31902912Sartem 		g_hash_table_replace (udi_to_method_queue, g_strdup (mi->udi), queue);
31912912Sartem 	} else {
31922912Sartem 		HAL_INFO (("no need to enqueue"));
31932912Sartem 		queue = g_list_append (NULL, mi);
31942912Sartem 		g_hash_table_insert (udi_to_method_queue, g_strdup (mi->udi), queue);
31952912Sartem 
31962912Sartem 		hald_exec_method_do_invocation (mi);
31972912Sartem 	}
31982912Sartem }
31992912Sartem 
32002912Sartem 
32012912Sartem static void
hald_exec_method_process_queue(const char * udi)32022912Sartem hald_exec_method_process_queue (const char *udi)
32032912Sartem {
32042912Sartem 	gpointer origkey;
32052912Sartem 	GList *queue;
32062912Sartem 	MethodInvocation *mi;
32072912Sartem 
32082912Sartem 	if (g_hash_table_lookup_extended (udi_to_method_queue, udi, &origkey, (gpointer) &queue)) {
32092912Sartem 
32102912Sartem 		/* clean the top of the list */
32112912Sartem 		if (queue != NULL) {
32122912Sartem 			mi = (MethodInvocation *) queue->data;
32132912Sartem 			queue = g_list_delete_link (queue, queue);
32142912Sartem 			if (queue == NULL) {
32152912Sartem 				g_hash_table_remove (udi_to_method_queue, udi);
32162912Sartem 				HAL_INFO (("No more methods in queue"));
32172912Sartem 			}
32182912Sartem 
32192912Sartem 			/* if method was Volume.Unmount() then refresh mount state */
32202912Sartem 			if (strcmp (mi->interface, "org.freedesktop.Hal.Device.Volume") == 0 &&
32212912Sartem 			    strcmp (mi->member, "Unmount") == 0) {
32222912Sartem 				HalDevice *d;
32232912Sartem 
32242912Sartem 				HAL_INFO (("Refreshing mount state for %s since Unmount() completed", mi->udi));
32252912Sartem 
32262912Sartem 				d = hal_device_store_find (hald_get_gdl (), mi->udi);
32272912Sartem 				if (d == NULL) {
32282912Sartem 					d = hal_device_store_find (hald_get_tdl (), mi->udi);
32292912Sartem 				}
32302912Sartem 
32312912Sartem 				if (d != NULL) {
32322912Sartem 					osspec_refresh_mount_state_for_block_device (d);
32332912Sartem 				} else {
32342912Sartem 					HAL_WARNING ((" Cannot find device object for %s", mi->udi));
32352912Sartem 				}
32362912Sartem 			}
32372912Sartem 
32382912Sartem 			hald_exec_method_free_mi (mi);
32392912Sartem 		}
32402912Sartem 
32412912Sartem 		/* process the rest of the list */
32422912Sartem 		if (queue != NULL) {
32432912Sartem 			HAL_INFO (("Execing next method in queue"));
32442912Sartem 			g_hash_table_replace (udi_to_method_queue, g_strdup (udi), queue);
32452912Sartem 
32462912Sartem 			mi = (MethodInvocation *) queue->data;
32472912Sartem 			if (!hald_exec_method_do_invocation (mi)) {
32482912Sartem 				/* the device went away before we got to it... */
32492912Sartem 				hald_exec_method_process_queue (mi->udi);
32502912Sartem 			}
32512912Sartem 		}
32522912Sartem 	}
32532912Sartem }
32542912Sartem 
32552912Sartem static void
hald_exec_method_cb(HalDevice * d,guint32 exit_type,gint return_code,gchar ** error,gpointer data1,gpointer data2)32562912Sartem hald_exec_method_cb (HalDevice *d, guint32 exit_type,
32572912Sartem 		     gint return_code, gchar **error,
32582912Sartem 		     gpointer data1, gpointer data2)
32592912Sartem {
32606573Sphitran 	dbus_int32_t result;
32612912Sartem 	DBusMessage *reply = NULL;
32622912Sartem 	DBusMessage *message;
32632912Sartem 	DBusMessageIter iter;
32642912Sartem 	DBusConnection *conn;
32652912Sartem 	gchar *exp_name = NULL;
32662912Sartem 	gchar *exp_detail = NULL;
3267*10659SXiao-Lin.Zhang@Sun.COM 	gboolean invalid_name = FALSE;
32682912Sartem 
32692912Sartem 	hald_exec_method_process_queue (d->udi);
32702912Sartem 
32712912Sartem 	message = (DBusMessage *) data1;
32722912Sartem 	conn = (DBusConnection *) data2;
32732912Sartem 
32742912Sartem 	if (exit_type == HALD_RUN_SUCCESS && error != NULL &&
32752912Sartem 	    error[0] != NULL && error[1] != NULL) {
32762912Sartem 		exp_name = error[0];
32772912Sartem 		if (error[0] != NULL) {
32782912Sartem 			exp_detail = error[1];
32792912Sartem 		}
32802912Sartem 		HAL_INFO (("failed with '%s' '%s'", exp_name, exp_detail));
32812912Sartem 	}
32822912Sartem 
32832912Sartem 	if (exit_type != HALD_RUN_SUCCESS) {
32842912Sartem 		reply = dbus_message_new_error (message, "org.freedesktop.Hal.Device.UnknownError", "An unknown error occured");
32852912Sartem 		if (conn != NULL) {
32862912Sartem 			if (!dbus_connection_send (conn, reply, NULL))
32872912Sartem 				DIE (("No memory"));
32882912Sartem 		}
32892912Sartem 		dbus_message_unref (reply);
32902912Sartem 	} else if (exp_name != NULL && exp_detail != NULL) {
3291*10659SXiao-Lin.Zhang@Sun.COM 		if (!is_valid_interface_name (exp_name)) {
3292*10659SXiao-Lin.Zhang@Sun.COM 			/*
3293*10659SXiao-Lin.Zhang@Sun.COM 			 * error name may be invalid,
3294*10659SXiao-Lin.Zhang@Sun.COM 			 * if so we need a generic HAL error name;
3295*10659SXiao-Lin.Zhang@Sun.COM 			 * otherwise, dbus will be messed up.
3296*10659SXiao-Lin.Zhang@Sun.COM 			 */
3297*10659SXiao-Lin.Zhang@Sun.COM 			invalid_name = TRUE;
3298*10659SXiao-Lin.Zhang@Sun.COM 			exp_detail = g_strconcat (exp_name, " \n ", exp_detail, NULL);
3299*10659SXiao-Lin.Zhang@Sun.COM 			exp_name = "org.freedesktop.Hal.Device.UnknownError";
3300*10659SXiao-Lin.Zhang@Sun.COM 		}
33012912Sartem 		reply = dbus_message_new_error (message, exp_name, exp_detail);
33022912Sartem 		if (reply == NULL) {
33032912Sartem 			/* error name may be invalid - assume caller fucked up and use a generic HAL error name */
33042912Sartem 			reply = dbus_message_new_error (message, "org.freedesktop.Hal.Device.UnknownError", "An unknown error occured");
33052912Sartem 			if (reply == NULL) {
33062912Sartem 				DIE (("No memory"));
33072912Sartem 			}
33082912Sartem 		}
33092912Sartem 		if (conn != NULL) {
33102912Sartem 			if (!dbus_connection_send (conn, reply, NULL))
33112912Sartem 				DIE (("No memory"));
33122912Sartem 		}
33132912Sartem 		dbus_message_unref (reply);
33142912Sartem 
33152912Sartem 	} else {
33166573Sphitran 		result = (dbus_int32_t) return_code;
33172912Sartem 
33182912Sartem 		reply = dbus_message_new_method_return (message);
33192912Sartem 		if (reply == NULL)
33202912Sartem 			DIE (("No memory"));
33212912Sartem 
33222912Sartem 		dbus_message_iter_init_append (reply, &iter);
33236573Sphitran 		dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &result);
33242912Sartem 
33252912Sartem 		if (conn != NULL) {
33262912Sartem 			if (!dbus_connection_send (conn, reply, NULL))
33272912Sartem 				DIE (("No memory"));
33282912Sartem 		}
33292912Sartem 
33302912Sartem 		dbus_message_unref (reply);
33312912Sartem 	}
33322912Sartem 
3333*10659SXiao-Lin.Zhang@Sun.COM 	if (invalid_name)
3334*10659SXiao-Lin.Zhang@Sun.COM 		g_free (exp_detail);
33352912Sartem 	dbus_message_unref (message);
33362912Sartem }
33372912Sartem 
33382912Sartem static DBusHandlerResult
hald_exec_method(HalDevice * d,DBusConnection * connection,dbus_bool_t local_interface,DBusMessage * message,const char * execpath)33392912Sartem hald_exec_method (HalDevice *d, DBusConnection *connection, dbus_bool_t local_interface,
33402912Sartem 		  DBusMessage *message, const char *execpath)
33412912Sartem {
33422912Sartem 	int type;
33432912Sartem 	GString *stdin_str;
33442912Sartem 	DBusMessageIter iter;
33452912Sartem 	char *extra_env[3];
33462912Sartem 	char uid_export[128];
33472912Sartem 	char sender_export[128];
33482912Sartem 	MethodInvocation *mi;
33492912Sartem 
33502912Sartem 	/* add calling uid */
33512912Sartem 	extra_env[0] = NULL;
33522912Sartem 	extra_env[1] = NULL;
33532912Sartem 	if (local_interface) {
33542912Sartem 		extra_env[0] = "HAL_METHOD_INVOKED_BY_UID=0";
33552912Sartem 		extra_env[1] = "HAL_METHOD_INVOKED_BY_SYSTEMBUS_CONNECTION_NAME=0";
33562912Sartem 	} else {
33572912Sartem 		const char *sender;
33582912Sartem 
33592912Sartem 		sender = dbus_message_get_sender (message);
33602912Sartem 		if (sender != NULL) {
33612912Sartem 			DBusError error;
33622912Sartem 			unsigned long uid;
33632912Sartem 
33642912Sartem 			dbus_error_init (&error);
33652912Sartem 			uid = dbus_bus_get_unix_user (connection, sender, &error);
33662912Sartem 			if (!dbus_error_is_set (&error)) {
33672912Sartem 				sprintf (uid_export, "HAL_METHOD_INVOKED_BY_UID=%lu", uid);
33682912Sartem 				extra_env[0] = uid_export;
33692912Sartem 			}
33702912Sartem 			snprintf (sender_export, sizeof (sender_export),
33712912Sartem 				  "HAL_METHOD_INVOKED_BY_SYSTEMBUS_CONNECTION_NAME=%s", sender);
33722912Sartem 			extra_env[1] = sender_export;
33732912Sartem 		}
33742912Sartem 	}
33752912Sartem 
33762912Sartem 	if (extra_env[0] == NULL)
33772912Sartem 		extra_env[0] = "HAL_METHOD_INVOKED_BY_UID=nobody";
33782912Sartem 	if (extra_env[1] == NULL)
33792912Sartem 		extra_env[1] = "HAL_METHOD_INVOKED_BY_SYSTEMBUS_CONNECTION_NAME=0";
33802912Sartem 
33812912Sartem 
33822912Sartem 	extra_env[2] = NULL;
33832912Sartem 
33842912Sartem 	/* prepare stdin with parameters */
33852912Sartem 	stdin_str = g_string_sized_new (256); /* default size for passing params; can grow */
33862912Sartem 	dbus_message_iter_init (message, &iter);
33872912Sartem 	while ((type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID) {
33882912Sartem 		switch (type) {
33892912Sartem 		case DBUS_TYPE_BYTE:
33902912Sartem 		{
33912912Sartem 			unsigned char value;
33922912Sartem 			dbus_message_iter_get_basic (&iter, &value);
33932912Sartem 			g_string_append_printf (stdin_str, "%u", value);
33942912Sartem 			break;
33952912Sartem 		}
33962912Sartem 		case DBUS_TYPE_INT16:
33972912Sartem 		{
33982912Sartem 			dbus_int16_t value;
33992912Sartem 			dbus_message_iter_get_basic (&iter, &value);
34002912Sartem 			g_string_append_printf (stdin_str, "%d", value);
34012912Sartem 			break;
34022912Sartem 		}
34032912Sartem 		case DBUS_TYPE_UINT16:
34042912Sartem 		{
34052912Sartem 			dbus_uint16_t value;
34062912Sartem 			dbus_message_iter_get_basic (&iter, &value);
34072912Sartem 			g_string_append_printf (stdin_str, "%u", value);
34082912Sartem 			break;
34092912Sartem 		}
34102912Sartem 		case DBUS_TYPE_INT32:
34112912Sartem 		{
34122912Sartem 			dbus_int32_t value;
34132912Sartem 			dbus_message_iter_get_basic (&iter, &value);
34142912Sartem 			g_string_append_printf (stdin_str, "%d", value);
34152912Sartem 			break;
34162912Sartem 		}
34172912Sartem 		case DBUS_TYPE_UINT32:
34182912Sartem 		{
34192912Sartem 			dbus_uint32_t value;
34202912Sartem 			dbus_message_iter_get_basic (&iter, &value);
34212912Sartem 			g_string_append_printf (stdin_str, "%u", value);
34222912Sartem 			break;
34232912Sartem 		}
34242912Sartem 		case DBUS_TYPE_INT64:
34252912Sartem 		{
34262912Sartem 			dbus_int64_t value;
34272912Sartem 			dbus_message_iter_get_basic (&iter, &value);
34282912Sartem 			g_string_append_printf (stdin_str, "%lld", (long long int) value);
34292912Sartem 			break;
34302912Sartem 		}
34312912Sartem 		case DBUS_TYPE_UINT64:
34322912Sartem 		{
34332912Sartem 			dbus_uint64_t value;
34342912Sartem 			dbus_message_iter_get_basic (&iter, &value);
34352912Sartem 			g_string_append_printf (stdin_str, "%llu", (long long unsigned int) value);
34362912Sartem 			break;
34372912Sartem 		}
34382912Sartem 		case DBUS_TYPE_DOUBLE:
34392912Sartem 		{
34402912Sartem 			double value;
34412912Sartem 			dbus_message_iter_get_basic (&iter, &value);
34422912Sartem 			g_string_append_printf (stdin_str, "%g", value);
34432912Sartem 			break;
34442912Sartem 		}
34452912Sartem 		case DBUS_TYPE_BOOLEAN:
34462912Sartem 		{
34472912Sartem 			dbus_bool_t value;
34482912Sartem 			dbus_message_iter_get_basic (&iter, &value);
34492912Sartem 			g_string_append (stdin_str, value ? "true" : "false");
34502912Sartem 			break;
34512912Sartem 		}
34522912Sartem 		case DBUS_TYPE_STRING:
34532912Sartem 		{
34542912Sartem 			char *value;
34552912Sartem 			dbus_message_iter_get_basic (&iter, &value);
34562912Sartem 			g_string_append (stdin_str, value);
34572912Sartem 			break;
34582912Sartem 		}
34592912Sartem 
34602912Sartem 		case DBUS_TYPE_ARRAY:
34612912Sartem 		{
34622912Sartem 			DBusMessageIter iter_strlist;
34632912Sartem 			if (dbus_message_iter_get_element_type (&iter) != DBUS_TYPE_STRING)
34642912Sartem 				goto error;
34652912Sartem 
34662912Sartem 			dbus_message_iter_recurse (&iter, &iter_strlist);
34672912Sartem 			while (dbus_message_iter_get_arg_type (&iter_strlist) == DBUS_TYPE_STRING) {
34682912Sartem 				const char *value;
34692912Sartem 				dbus_message_iter_get_basic (&iter_strlist, &value);
34702912Sartem 				g_string_append (stdin_str, value);
34712912Sartem 				g_string_append (stdin_str, "\t");
34722912Sartem 				dbus_message_iter_next(&iter_strlist);
34732912Sartem 			}
34742912Sartem 			break;
34752912Sartem 		}
34762912Sartem 
34772912Sartem 		default:
34782912Sartem 			goto error;
34792912Sartem 		}
34802912Sartem 
34812912Sartem 		g_string_append_c (stdin_str, '\n');
34822912Sartem 		dbus_message_iter_next (&iter);
34832912Sartem 	}
34842912Sartem 
34852912Sartem 	mi = g_new0 (MethodInvocation, 1);
34862912Sartem 	mi->udi = g_strdup (d->udi);
34872912Sartem 	mi->execpath = g_strdup (execpath);
34882912Sartem 	mi->extra_env = g_strdupv (extra_env);
34892912Sartem 	mi->mstdin = g_strdup (stdin_str->str);
34902912Sartem 	mi->message = message;
34912912Sartem 	mi->connection = connection;
34922912Sartem 	mi->member = g_strdup (dbus_message_get_member (message));
34932912Sartem 	mi->interface = g_strdup (dbus_message_get_interface (message));
34942912Sartem 	hald_exec_method_enqueue (mi);
34952912Sartem 
34962912Sartem 	dbus_message_ref (message);
34972912Sartem 	g_string_free (stdin_str, TRUE);
34982912Sartem 
34992912Sartem 	return DBUS_HANDLER_RESULT_HANDLED;
35002912Sartem 
35012912Sartem error:
35022912Sartem 	g_string_free (stdin_str, TRUE);
35032912Sartem 	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
35042912Sartem }
35052912Sartem 
35062912Sartem static gboolean
foreach_device_get_xml_node(HalDeviceStore * store,HalDevice * device,gpointer user_data)35072912Sartem foreach_device_get_xml_node (HalDeviceStore *store, HalDevice *device,
35082912Sartem 			     gpointer user_data)
35092912Sartem {
35102912Sartem 	GString *xml = user_data;
35112912Sartem 	const char *udi, *name;
35122912Sartem 
35132912Sartem 	udi = hal_device_get_udi (device);
35142912Sartem 	name = strrchr(udi, '/')+1;
35152912Sartem 
35162912Sartem 	xml = g_string_append(xml, "  <node name=\"");
35172912Sartem 	xml = g_string_append(xml, name);
35182912Sartem 	xml = g_string_append(xml, "\"/>\n");
35192912Sartem 
35202912Sartem 	return TRUE;
35212912Sartem }
35222912Sartem 
35232912Sartem static DBusHandlerResult
do_introspect(DBusConnection * connection,DBusMessage * message,dbus_bool_t local_interface)35242912Sartem do_introspect (DBusConnection  *connection,
35252912Sartem 	       DBusMessage     *message,
35262912Sartem 	       dbus_bool_t      local_interface)
35272912Sartem {
35282912Sartem 	const char *path;
35292912Sartem 	DBusMessage *reply;
35302912Sartem 	GString *xml;
35312912Sartem 	char *xml_string;
35322912Sartem 
35332912Sartem 	HAL_TRACE (("entering do_introspect"));
35342912Sartem 
35352912Sartem 	path = dbus_message_get_path (message);
35362912Sartem 
35372912Sartem 	xml = g_string_new ("<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n"
35382912Sartem 			    "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
35392912Sartem 			    "<node>\n"
35402912Sartem 			    "  <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
35412912Sartem 			    "    <method name=\"Introspect\">\n"
35422912Sartem 			    "      <arg name=\"data\" direction=\"out\" type=\"s\"/>\n"
35432912Sartem 			    "    </method>\n"
35442912Sartem 			    "  </interface>\n");
35452912Sartem 
35462912Sartem 	if (strcmp (path, "/") == 0) {
35472912Sartem 
35482912Sartem 		xml = g_string_append (xml,
35492912Sartem 				       "  <node name=\"org\"/>\n");
35502912Sartem 
35512912Sartem 	} else if (strcmp (path, "/org") == 0) {
35522912Sartem 
35532912Sartem 		xml = g_string_append (xml,
35542912Sartem 				       "  <node name=\"freedesktop\"/>\n");
35552912Sartem 
35562912Sartem 	} else if (strcmp (path, "/org/freedesktop") == 0) {
35572912Sartem 
35582912Sartem 		xml = g_string_append (xml,
35592912Sartem 				       "  <node name=\"Hal\"/>\n");
35602912Sartem 
35612912Sartem 	} else if (strcmp (path, "/org/freedesktop/Hal") == 0) {
35622912Sartem 
35632912Sartem 		xml = g_string_append (xml,
35642912Sartem 				       "  <node name=\"Manager\"/>\n"
35652912Sartem 				       "  <node name=\"devices\"/>\n");
35662912Sartem 
35672912Sartem 	} else if (strcmp (path, "/org/freedesktop/Hal/devices") == 0) {
35682912Sartem 
35692912Sartem 		hal_device_store_foreach (hald_get_gdl (),
35702912Sartem 					  foreach_device_get_xml_node,
35712912Sartem 					  xml);
35722912Sartem 
35732912Sartem 	} else if (strcmp (path, "/org/freedesktop/Hal/Manager") == 0) {
35742912Sartem 
35752912Sartem 		xml = g_string_append (xml,
35762912Sartem 				       "  <interface name=\"org.freedesktop.Hal.Manager\">\n"
35772912Sartem 				       "    <method name=\"GetAllDevices\">\n"
35782912Sartem 				       "      <arg name=\"devices\" direction=\"out\" type=\"ao\"/>\n"
35792912Sartem 				       "    </method>\n"
35802912Sartem 				       "    <method name=\"DeviceExists\">\n"
35812912Sartem 				       "      <arg name=\"does_it_exist\" direction=\"out\" type=\"b\"/>\n"
35822912Sartem 				       "      <arg name=\"udi\" direction=\"in\" type=\"o\"/>\n"
35832912Sartem 				       "    </method>\n"
35842912Sartem 				       "    <method name=\"FindDeviceStringMatch\">\n"
35852912Sartem 				       "      <arg name=\"devices\" direction=\"out\" type=\"ao\"/>\n"
35862912Sartem 				       "      <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
35872912Sartem 				       "      <arg name=\"value\" direction=\"in\" type=\"s\"/>\n"
35882912Sartem 				       "    </method>\n"
35892912Sartem 				       "    <method name=\"FindDeviceByCapability\">\n"
35902912Sartem 				       "      <arg name=\"devices\" direction=\"out\" type=\"ao\"/>\n"
35912912Sartem 				       "      <arg name=\"capability\" direction=\"in\" type=\"s\"/>\n"
35922912Sartem 				       "    </method>\n"
35932912Sartem 				       "    <method name=\"ClaimBranch\">\n"
35942912Sartem 				       "      <arg name=\"udi\" direction=\"in\" type=\"o\"/>\n"
35952912Sartem 				       "      <arg name=\"claim_service\" direction=\"in\" type=\"s\"/>\n"
35962912Sartem 				       "      <arg name=\"result\" direction=\"out\" type=\"b\"/>\n"
35972912Sartem 				       "    </method>\n"
35982912Sartem 				       "    <method name=\"UnclaimBranch\">\n"
35992912Sartem 				       "      <arg name=\"udi\" direction=\"in\" type=\"o\"/>\n"
36002912Sartem 				       "      <arg name=\"result\" direction=\"out\" type=\"b\"/>\n"
36012912Sartem 				       "    </method>\n"
36022912Sartem 				       "    <method name=\"NewDevice\">\n"
36032912Sartem 				       "      <arg name=\"temporary_udi\" direction=\"out\" type=\"s\"/>\n"
36042912Sartem 				       "    </method>\n"
36052912Sartem 				       "    <method name=\"Remove\">\n"
36062912Sartem 				       "      <arg name=\"udi\" direction=\"in\" type=\"s\"/>\n"
36072912Sartem 				       "    </method>\n"
36082912Sartem 				       "    <method name=\"CommitToGdl\">\n"
36092912Sartem 				       "      <arg name=\"temporary_udi\" direction=\"in\" type=\"s\"/>\n"
36102912Sartem 				       "      <arg name=\"global_udi\" direction=\"in\" type=\"s\"/>\n"
36112912Sartem 				       "    </method>\n"
36122912Sartem 				       "  </interface>\n");
36132912Sartem 	} else {
36142912Sartem 		HalDevice *d;
36152912Sartem 
36162912Sartem 		d = hal_device_store_find (hald_get_gdl (), path);
36172912Sartem 		if (d == NULL)
36182912Sartem 			d = hal_device_store_find (hald_get_tdl (), path);
36192912Sartem 
36202912Sartem 		if (d == NULL) {
36212912Sartem 			raise_no_such_device (connection, message, path);
36222912Sartem 			return DBUS_HANDLER_RESULT_HANDLED;
36232912Sartem 		}
36242912Sartem 
36252912Sartem 		xml = g_string_append (xml,
36262912Sartem 				       "  <interface name=\"org.freedesktop.Hal.Device\">\n"
36272912Sartem 				       "    <method name=\"GetAllProperties\">\n"
36282912Sartem 				       "      <arg name=\"properties\" direction=\"out\" type=\"a{sv}\"/>\n"
36292912Sartem 				       "    </method>\n"
36302912Sartem 				       "    <method name=\"SetMultipleProperties\">\n"
36312912Sartem 				       "      <arg name=\"properties\" direction=\"in\" type=\"a{sv}\"/>\n"
36322912Sartem 				       "    </method>\n"
36332912Sartem 				       "    <method name=\"GetProperty\">\n"
36342912Sartem 				       "      <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
36352912Sartem 				       "      <arg name=\"value\" direction=\"out\" type=\"v\"/>\n"
36362912Sartem 				       "    </method>\n"
36372912Sartem 				       "    <method name=\"GetPropertyString\">\n"
36382912Sartem 				       "      <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
36392912Sartem 				       "      <arg name=\"value\" direction=\"out\" type=\"s\"/>\n"
36402912Sartem 				       "    </method>\n"
36412912Sartem 				       "    <method name=\"GetPropertyStringList\">\n"
36422912Sartem 				       "      <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
36432912Sartem 				       "      <arg name=\"value\" direction=\"out\" type=\"as\"/>\n"
36442912Sartem 				       "    </method>\n"
36452912Sartem 				       "    <method name=\"GetPropertyInteger\">\n"
36462912Sartem 				       "      <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
36472912Sartem 				       "      <arg name=\"value\" direction=\"out\" type=\"i\"/>\n"
36482912Sartem 				       "    </method>\n"
36492912Sartem 				       "    <method name=\"GetPropertyBoolean\">\n"
36502912Sartem 				       "      <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
36512912Sartem 				       "      <arg name=\"value\" direction=\"out\" type=\"b\"/>\n"
36522912Sartem 				       "    </method>\n"
36532912Sartem 				       "    <method name=\"GetPropertyDouble\">\n"
36542912Sartem 				       "      <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
36552912Sartem 				       "      <arg name=\"value\" direction=\"out\" type=\"d\"/>\n"
36562912Sartem 				       "    </method>\n"
36572912Sartem 				       "    <method name=\"SetProperty\">\n"
36582912Sartem 				       "      <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
36592912Sartem 				       "      <arg name=\"value\" direction=\"in\" type=\"v\"/>\n"
36602912Sartem 				       "    </method>\n"
36612912Sartem 				       "    <method name=\"SetPropertyString\">\n"
36622912Sartem 				       "      <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
36632912Sartem 				       "      <arg name=\"value\" direction=\"in\" type=\"s\"/>\n"
36642912Sartem 				       "    </method>\n"
36652912Sartem 				       "    <method name=\"SetPropertyStringList\">\n"
36662912Sartem 				       "      <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
36672912Sartem 				       "      <arg name=\"value\" direction=\"in\" type=\"as\"/>\n"
36682912Sartem 				       "    </method>\n"
36692912Sartem 				       "    <method name=\"SetPropertyInteger\">\n"
36702912Sartem 				       "      <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
36712912Sartem 				       "      <arg name=\"value\" direction=\"in\" type=\"i\"/>\n"
36722912Sartem 				       "    </method>\n"
36732912Sartem 				       "    <method name=\"SetPropertyBoolean\">\n"
36742912Sartem 				       "      <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
36752912Sartem 				       "      <arg name=\"value\" direction=\"in\" type=\"b\"/>\n"
36762912Sartem 				       "    </method>\n"
36772912Sartem 				       "    <method name=\"SetPropertyDouble\">\n"
36782912Sartem 				       "      <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
36792912Sartem 				       "      <arg name=\"value\" direction=\"in\" type=\"d\"/>\n"
36802912Sartem 				       "    </method>\n"
36812912Sartem 
36822912Sartem 				       "    <method name=\"RemoveProperty\">\n"
36832912Sartem 				       "      <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
36842912Sartem 				       "    </method>\n"
36852912Sartem 				       "    <method name=\"GetPropertyType\">\n"
36862912Sartem 				       "      <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
36872912Sartem 				       "      <arg name=\"type\" direction=\"out\" type=\"i\"/>\n"
36882912Sartem 				       "    </method>\n"
36892912Sartem 				       "    <method name=\"PropertyExists\">\n"
36902912Sartem 				       "      <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
36912912Sartem 				       "      <arg name=\"does_it_exist\" direction=\"out\" type=\"b\"/>\n"
36922912Sartem 				       "    </method>\n"
36932912Sartem 				       "    <method name=\"AddCapability\">\n"
36942912Sartem 				       "      <arg name=\"capability\" direction=\"in\" type=\"s\"/>\n"
36952912Sartem 				       "    </method>\n"
36962912Sartem 				       "    <method name=\"QueryCapability\">\n"
36972912Sartem 				       "      <arg name=\"capability\" direction=\"in\" type=\"s\"/>\n"
36982912Sartem 				       "      <arg name=\"does_it_have_capability\" direction=\"out\" type=\"b\"/>\n"
36992912Sartem 				       "    </method>\n"
37002912Sartem 				       "    <method name=\"Lock\">\n"
37012912Sartem 				       "      <arg name=\"reason\" direction=\"in\" type=\"s\"/>\n"
37022912Sartem 				       "      <arg name=\"acquired_lock\" direction=\"out\" type=\"b\"/>\n"
37032912Sartem 				       "    </method>\n"
37042912Sartem 				       "    <method name=\"Unlock\">\n"
37052912Sartem 				       "      <arg name=\"released_lock\" direction=\"out\" type=\"b\"/>\n"
37062912Sartem 				       "    </method>\n"
37072912Sartem 
37082912Sartem 				       "    <method name=\"StringListAppend\">\n"
37092912Sartem 				       "      <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
37102912Sartem 				       "      <arg name=\"value\" direction=\"in\" type=\"s\"/>\n"
37112912Sartem 				       "    </method>\n"
37122912Sartem 				       "    <method name=\"StringListPrepend\">\n"
37132912Sartem 				       "      <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
37142912Sartem 				       "      <arg name=\"value\" direction=\"in\" type=\"s\"/>\n"
37152912Sartem 				       "    </method>\n"
37162912Sartem 				       "    <method name=\"StringListRemove\">\n"
37172912Sartem 				       "      <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
37182912Sartem 				       "      <arg name=\"value\" direction=\"in\" type=\"s\"/>\n"
37192912Sartem 				       "    </method>\n"
37202912Sartem 				       "    <method name=\"EmitCondition\">\n"
37212912Sartem 				       "      <arg name=\"condition_name\" direction=\"in\" type=\"s\"/>\n"
37222912Sartem 				       "      <arg name=\"condition_details\" direction=\"in\" type=\"s\"/>\n"
37232912Sartem 				       "      <arg name=\"rc\" direction=\"out\" type=\"b\"/>\n"
37242912Sartem 				       "    </method>\n"
37252912Sartem 
37262912Sartem 				       "    <method name=\"Rescan\">\n"
37272912Sartem 				       "      <arg name=\"call_had_sideeffect\" direction=\"out\" type=\"b\"/>\n"
37282912Sartem 				       "    </method>\n"
37292912Sartem 				       "    <method name=\"Reprobe\">\n"
37302912Sartem 				       "      <arg name=\"call_had_sideeffect\" direction=\"out\" type=\"b\"/>\n"
37312912Sartem 				       "    </method>\n"
37322912Sartem 
37332912Sartem 				       "    <method name=\"ClaimInterface\">\n"
37342912Sartem 				       "      <arg name=\"interface_name\" direction=\"in\" type=\"s\"/>\n"
37352912Sartem 				       "      <arg name=\"introspection_xml\" direction=\"in\" type=\"s\"/>\n"
37362912Sartem 				       "      <arg name=\"rc\" direction=\"out\" type=\"b\"/>\n"
37372912Sartem 				       "    </method>\n"
37382912Sartem 
37392912Sartem 				       "    <method name=\"AddonIsReady\">\n"
37402912Sartem 				       "      <arg name=\"rc\" direction=\"out\" type=\"b\"/>\n"
37412912Sartem 				       "    </method>\n"
37422912Sartem 
37432912Sartem 				       "  </interface>\n");
37442912Sartem 
37452912Sartem 			GSList *interfaces;
37462912Sartem 			GSList *i;
37472912Sartem 
37482912Sartem 			interfaces = hal_device_property_get_strlist (d, "info.interfaces");
37492912Sartem 			for (i = interfaces; i != NULL; i = g_slist_next (i)) {
37502912Sartem 				const char *ifname = (const char *) i->data;
37512912Sartem 				char *method_names_prop;
37522912Sartem 				char *method_signatures_prop;
37532912Sartem 				char *method_argnames_prop;
37542912Sartem 				GSList *method_names;
37552912Sartem 				GSList *method_signatures;
37562912Sartem 				GSList *method_argnames;
37572912Sartem 				GSList *j;
37582912Sartem 				GSList *k;
37592912Sartem 				GSList *l;
37602912Sartem 
37612912Sartem 				g_string_append_printf (xml, "  <interface name=\"%s\">\n", ifname);
37622912Sartem 
37632912Sartem 				method_names_prop = g_strdup_printf ("%s.method_names", ifname);
37642912Sartem 				method_signatures_prop = g_strdup_printf ("%s.method_signatures", ifname);
37652912Sartem 				method_argnames_prop = g_strdup_printf ("%s.method_argnames", ifname);
37662912Sartem 
37672912Sartem 				method_names = hal_device_property_get_strlist (d, method_names_prop);
37682912Sartem 				method_signatures = hal_device_property_get_strlist (d, method_signatures_prop);
37692912Sartem 				method_argnames = hal_device_property_get_strlist (d, method_argnames_prop);
37702912Sartem 
37712912Sartem 				/* consult local list */
37722912Sartem 				if (method_names == NULL) {
37732912Sartem 					GSList *i;
37742912Sartem 
37752912Sartem 					for (i = helper_interface_handlers; i != NULL; i = g_slist_next (i)) {
37762912Sartem 						HelperInterfaceHandler *hih = i->data;
37772912Sartem 						if (strcmp (hih->udi, path) == 0) {
37782912Sartem 							xml = g_string_append (xml, hih->introspection_xml);
37792912Sartem 						}
37802912Sartem 					}
37812912Sartem 
37822912Sartem 				}
37832912Sartem 
37842912Sartem 				for (j = method_names, k = method_signatures, l = method_argnames;
37852912Sartem 				     j != NULL && k != NULL && l != NULL;
37862912Sartem 				     j = g_slist_next (j), k = g_slist_next (k), l = g_slist_next (l)) {
37872912Sartem 					const char *name;
37882912Sartem 					const char *sig;
37892912Sartem 					const char *argnames;
37902912Sartem 					char **args;
37912912Sartem 					unsigned int n;
37922912Sartem 					unsigned int m;
37932912Sartem 
37942912Sartem 					name = j->data;
37952912Sartem 					sig = k->data;
37962912Sartem 					argnames = l->data;
37972912Sartem 
37982912Sartem 					args = g_strsplit (argnames, " ", 0);
37992912Sartem 
38002912Sartem 					g_string_append_printf (xml, "    <method name=\"%s\">\n", name);
38012912Sartem 
38022912Sartem 					for (n = 0, m = 0; n < strlen (sig) && args[m] != NULL; n++, m++) {
38032912Sartem 						switch (sig[n]) {
38042912Sartem 						case 'a':
38052912Sartem 							if (n == strlen (sig) - 1) {
38062912Sartem 								HAL_WARNING (("Broken signature for method %s "
38072912Sartem 									      "on interface %s for object %s",
38082912Sartem 									      name, ifname, path));
38092912Sartem 								continue;
38102912Sartem 							}
38112912Sartem 							g_string_append_printf (
38122912Sartem 							  xml,
38132912Sartem 							  "      <arg name=\"%s\" direction=\"in\" type=\"a%c\"/>\n",
38142912Sartem 							  args[m], sig[n + 1]);
38152912Sartem 							n++;
38162912Sartem 							break;
38172912Sartem 
38182912Sartem 						default:
38192912Sartem 							g_string_append_printf (
38202912Sartem 							  xml,
38212912Sartem 							  "      <arg name=\"%s\" direction=\"in\" type=\"%c\"/>\n",
38222912Sartem 							  args[m], sig[n]);
38232912Sartem 							break;
38242912Sartem 						}
38252912Sartem 					}
38262912Sartem 					xml = g_string_append (
38272912Sartem 						xml,
38282912Sartem 						"      <arg name=\"return_code\" direction=\"out\" type=\"i\"/>\n");
38292912Sartem 					xml = g_string_append  (
38302912Sartem 						xml,
38312912Sartem 						"    </method>\n");
38322912Sartem 
38332912Sartem 				}
38342912Sartem 
38352912Sartem 
38362912Sartem 				xml = g_string_append (xml, "  </interface>\n");
38372912Sartem 
38382912Sartem 				g_free (method_names_prop);
38392912Sartem 				g_free (method_signatures_prop);
38402912Sartem 				g_free (method_argnames_prop);
38412912Sartem 			}
38422912Sartem 
38432912Sartem 	}
38442912Sartem 
38452912Sartem 	reply = dbus_message_new_method_return (message);
38462912Sartem 
38472912Sartem 	xml = g_string_append (xml, "</node>\n");
38482912Sartem 	xml_string = g_string_free (xml, FALSE);
38492912Sartem 
38502912Sartem 	dbus_message_append_args (reply,
38512912Sartem 				  DBUS_TYPE_STRING, &xml_string,
38522912Sartem 				  DBUS_TYPE_INVALID);
38532912Sartem 
38542912Sartem 	g_free (xml_string);
38552912Sartem 
38562912Sartem 	if (reply == NULL)
38572912Sartem 		DIE (("No memory"));
38582912Sartem 
38592912Sartem 	if (!dbus_connection_send (connection, reply, NULL))
38602912Sartem 		DIE (("No memory"));
38612912Sartem 
38622912Sartem 	dbus_message_unref (reply);
38632912Sartem 	return DBUS_HANDLER_RESULT_HANDLED;
38642912Sartem }
38652912Sartem 
38662912Sartem static void
reply_from_fwd_message(DBusPendingCall * pending_call,void * user_data)38672912Sartem reply_from_fwd_message (DBusPendingCall *pending_call,
38682912Sartem 			void            *user_data)
38692912Sartem {
38702912Sartem 	DBusMessage *reply_from_addon;
38712912Sartem 	DBusMessage *method_from_caller;
38722912Sartem 	DBusMessage *reply;
38732912Sartem 
38742912Sartem 	/*HAL_INFO (("in reply_from_fwd_message : user_data = 0x%x", user_data));*/
38752912Sartem 
38762912Sartem 	method_from_caller = (DBusMessage *) user_data;
38772912Sartem 	reply_from_addon = dbus_pending_call_steal_reply (pending_call);
38782912Sartem 
38792912Sartem 	reply = dbus_message_copy (reply_from_addon);
38802912Sartem 	dbus_message_set_destination (reply, dbus_message_get_sender (method_from_caller));
38812912Sartem 	dbus_message_set_reply_serial (reply, dbus_message_get_serial (method_from_caller));
38822912Sartem 
38832912Sartem 	if (dbus_connection != NULL)
38842912Sartem 		dbus_connection_send (dbus_connection, reply, NULL);
38852912Sartem 
38862912Sartem 	dbus_message_unref (reply_from_addon);
38872912Sartem 	dbus_message_unref (reply);
38882912Sartem 	dbus_message_unref (method_from_caller);
38892912Sartem 	dbus_pending_call_unref (pending_call);
38902912Sartem }
38912912Sartem 
38922912Sartem static DBusHandlerResult
hald_dbus_filter_handle_methods(DBusConnection * connection,DBusMessage * message,void * user_data,dbus_bool_t local_interface)38932912Sartem hald_dbus_filter_handle_methods (DBusConnection *connection, DBusMessage *message,
38942912Sartem 				 void *user_data, dbus_bool_t local_interface)
38952912Sartem {
38962912Sartem 	/*HAL_INFO (("connection=0x%x obj_path=%s interface=%s method=%s local_interface=%d",
38972912Sartem 		   connection,
38982912Sartem 		   dbus_message_get_path (message),
38992912Sartem 		   dbus_message_get_interface (message),
39002912Sartem 		   dbus_message_get_member (message),
39012912Sartem 		   local_interface));*/
39022912Sartem 
39032912Sartem 	if (dbus_message_is_method_call (message,
39042912Sartem 					 "org.freedesktop.Hal.Manager",
39052912Sartem 					 "GetAllDevices") &&
39062912Sartem 		   strcmp (dbus_message_get_path (message),
39072912Sartem 			   "/org/freedesktop/Hal/Manager") == 0) {
39082912Sartem 		return manager_get_all_devices (connection, message);
39092912Sartem 	} else if (dbus_message_is_method_call (message,
39102912Sartem 						"org.freedesktop.Hal.Manager",
39112912Sartem 						"DeviceExists") &&
39122912Sartem 		   strcmp (dbus_message_get_path (message),
39132912Sartem 			   "/org/freedesktop/Hal/Manager") == 0) {
39142912Sartem 		return manager_device_exists (connection, message);
39152912Sartem 	} else if (dbus_message_is_method_call (message,
39162912Sartem 						"org.freedesktop.Hal.Manager",
39172912Sartem 						"FindDeviceStringMatch") &&
39182912Sartem 		   strcmp (dbus_message_get_path (message),
39192912Sartem 			   "/org/freedesktop/Hal/Manager") == 0) {
39202912Sartem 		return manager_find_device_string_match (connection,
39212912Sartem 							 message);
39222912Sartem 	} else if (dbus_message_is_method_call
39232912Sartem 		   (message, "org.freedesktop.Hal.Manager",
39242912Sartem 		    "FindDeviceByCapability")
39252912Sartem 		   && strcmp (dbus_message_get_path (message),
39262912Sartem 			      "/org/freedesktop/Hal/Manager") == 0) {
39272912Sartem 		return manager_find_device_by_capability (connection,
39282912Sartem 							  message);
39292912Sartem 	} else if (dbus_message_is_method_call (message,
39302912Sartem 						"org.freedesktop.Hal.Manager",
39312912Sartem 						"ClaimBranch") &&
39322912Sartem 		   strcmp (dbus_message_get_path (message),
39332912Sartem 			   "/org/freedesktop/Hal/Manager") == 0) {
39342912Sartem 		return manager_claim_branch (connection, message);
39352912Sartem 	} else if (dbus_message_is_method_call (message,
39362912Sartem 						"org.freedesktop.Hal.Manager",
39372912Sartem 						"UnclaimBranch") &&
39382912Sartem 		   strcmp (dbus_message_get_path (message),
39392912Sartem 			   "/org/freedesktop/Hal/Manager") == 0) {
39402912Sartem 		return manager_unclaim_branch (connection, message);
39412912Sartem 	} else if (dbus_message_is_method_call (message,
39422912Sartem 						"org.freedesktop.Hal.Manager",
39432912Sartem 						"NewDevice") &&
39442912Sartem 		   strcmp (dbus_message_get_path (message),
39452912Sartem 			    "/org/freedesktop/Hal/Manager") == 0) {
39462912Sartem 		return manager_new_device (connection, message, local_interface);
39472912Sartem 	} else if (dbus_message_is_method_call (message,
39482912Sartem 						"org.freedesktop.Hal.Manager",
39492912Sartem 						"Remove") &&
39502912Sartem 		   strcmp (dbus_message_get_path (message),
39512912Sartem 			    "/org/freedesktop/Hal/Manager") == 0) {
39522912Sartem 		return manager_remove (connection, message, local_interface);
39532912Sartem 	} else if (dbus_message_is_method_call (message,
39542912Sartem 						"org.freedesktop.Hal.Manager",
39552912Sartem 						"CommitToGdl") &&
39562912Sartem 		   strcmp (dbus_message_get_path (message),
39572912Sartem 			    "/org/freedesktop/Hal/Manager") == 0) {
39582912Sartem 		return manager_commit_to_gdl (connection, message, local_interface);
39592912Sartem 	} else if (dbus_message_is_method_call (message,
39602912Sartem 					      "org.freedesktop.Hal.Device",
39612912Sartem 					      "GetAllProperties")) {
39622912Sartem 		return device_get_all_properties (connection, message);
39632912Sartem 	} else if (dbus_message_is_method_call (message,
39642912Sartem 					      "org.freedesktop.Hal.Device",
39652912Sartem 					      "SetMultipleProperties")) {
39662912Sartem 		return device_set_multiple_properties (connection, message, local_interface);
39672912Sartem 	} else if (dbus_message_is_method_call (message,
39682912Sartem 						"org.freedesktop.Hal.Device",
39692912Sartem 						"GetProperty")) {
39702912Sartem 		return device_get_property (connection, message);
39712912Sartem 	} else if (dbus_message_is_method_call (message,
39722912Sartem 						"org.freedesktop.Hal.Device",
39732912Sartem 						"GetPropertyString")) {
39742912Sartem 		return device_get_property (connection, message);
39752912Sartem 	} else if (dbus_message_is_method_call (message,
39762912Sartem 						"org.freedesktop.Hal.Device",
39772912Sartem 						"GetPropertyStringList")) {
39782912Sartem 		return device_get_property (connection, message);
39792912Sartem 	} else if (dbus_message_is_method_call (message,
39802912Sartem 						"org.freedesktop.Hal.Device",
39812912Sartem 						"GetPropertyInteger")) {
39822912Sartem 		return device_get_property (connection, message);
39832912Sartem 	} else if (dbus_message_is_method_call (message,
39842912Sartem 						"org.freedesktop.Hal.Device",
39852912Sartem 						"GetPropertyBoolean")) {
39862912Sartem 		return device_get_property (connection, message);
39872912Sartem 	} else if (dbus_message_is_method_call (message,
39882912Sartem 						"org.freedesktop.Hal.Device",
39892912Sartem 						"GetPropertyDouble")) {
39902912Sartem 		return device_get_property (connection, message);
39912912Sartem 	} else if (dbus_message_is_method_call (message,
39922912Sartem 						"org.freedesktop.Hal.Device",
39932912Sartem 						"SetProperty")) {
39942912Sartem 		return device_set_property (connection, message, local_interface);
39952912Sartem 	} else if (dbus_message_is_method_call (message,
39962912Sartem 						"org.freedesktop.Hal.Device",
39972912Sartem 						"SetPropertyString")) {
39982912Sartem 		return device_set_property (connection, message, local_interface);
39992912Sartem 	} else if (dbus_message_is_method_call (message,
40002912Sartem 						"org.freedesktop.Hal.Device",
40012912Sartem 						"SetPropertyInteger")) {
40022912Sartem 		return device_set_property (connection, message, local_interface);
40032912Sartem 	} else if (dbus_message_is_method_call (message,
40042912Sartem 						"org.freedesktop.Hal.Device",
40052912Sartem 						"SetPropertyBoolean")) {
40062912Sartem 		return device_set_property (connection, message, local_interface);
40072912Sartem 	} else if (dbus_message_is_method_call (message,
40082912Sartem 						"org.freedesktop.Hal.Device",
40092912Sartem 						"SetPropertyDouble")) {
40102912Sartem 		return device_set_property (connection, message, local_interface);
40112912Sartem 	} else if (dbus_message_is_method_call (message,
40122912Sartem 						"org.freedesktop.Hal.Device",
40132912Sartem 						"RemoveProperty")) {
40142912Sartem 		return device_remove_property (connection, message, local_interface);
40152912Sartem 	} else if (dbus_message_is_method_call (message,
40162912Sartem 						"org.freedesktop.Hal.Device",
40172912Sartem 						"GetPropertyType")) {
40182912Sartem 		return device_get_property_type (connection, message);
40192912Sartem 	} else if (dbus_message_is_method_call (message,
40202912Sartem 						"org.freedesktop.Hal.Device",
40212912Sartem 						"PropertyExists")) {
40222912Sartem 		return device_property_exists (connection, message);
40232912Sartem 	} else if (dbus_message_is_method_call (message,
40242912Sartem 						"org.freedesktop.Hal.Device",
40252912Sartem 						"AddCapability")) {
40262912Sartem 		return device_add_capability (connection, message, local_interface);
40272912Sartem 	} else if (dbus_message_is_method_call (message,
40282912Sartem 						"org.freedesktop.Hal.Device",
40292912Sartem 						"QueryCapability")) {
40302912Sartem 		return device_query_capability (connection, message);
40312912Sartem 	} else if (dbus_message_is_method_call (message,
40322912Sartem 						"org.freedesktop.Hal.Device",
40332912Sartem 						"Lock")) {
40342912Sartem 		return device_lock (connection, message);
40352912Sartem 	} else if (dbus_message_is_method_call (message,
40362912Sartem 						"org.freedesktop.Hal.Device",
40372912Sartem 						"Unlock")) {
40382912Sartem 		return device_unlock (connection, message);
40392912Sartem 	} else if (dbus_message_is_method_call (message,
40402912Sartem 						"org.freedesktop.Hal.Device",
40412912Sartem 						"StringListAppend")) {
40422912Sartem 		return device_string_list_append_prepend (connection, message, FALSE);
40432912Sartem 	} else if (dbus_message_is_method_call (message,
40442912Sartem 						"org.freedesktop.Hal.Device",
40452912Sartem 						"StringListPrepend")) {
40462912Sartem 		return device_string_list_append_prepend (connection, message, TRUE);
40472912Sartem 	} else if (dbus_message_is_method_call (message,
40482912Sartem 						"org.freedesktop.Hal.Device",
40492912Sartem 						"StringListRemove")) {
40502912Sartem 		return device_string_list_remove (connection, message);
40512912Sartem 	} else if (dbus_message_is_method_call (message,
40522912Sartem 						"org.freedesktop.Hal.Device",
40532912Sartem 						"Rescan")) {
40542912Sartem 		return device_rescan (connection, message, local_interface);
40552912Sartem 	} else if (dbus_message_is_method_call (message,
40562912Sartem 						"org.freedesktop.Hal.Device",
40572912Sartem 						"Reprobe")) {
40582912Sartem 		return device_reprobe (connection, message, local_interface);
40592912Sartem 	} else if (dbus_message_is_method_call (message,
40602912Sartem 						"org.freedesktop.Hal.Device",
40612912Sartem 						"EmitCondition")) {
40622912Sartem 		return device_emit_condition (connection, message, local_interface);
40632912Sartem 	} else if (dbus_message_is_method_call (message,
40642912Sartem 						"org.freedesktop.Hal.Device",
40652912Sartem 						"ClaimInterface")) {
40662912Sartem 		return device_claim_interface (connection, message, local_interface);
40672912Sartem #if 0
40682912Sartem 	} else if (dbus_message_is_method_call (message,
40692912Sartem 						"org.freedesktop.Hal.Device",
40702912Sartem 						"ReleaseInterface")) {
40712912Sartem 		return device_release_interface (connection, message, local_interface);
40722912Sartem #endif
40732912Sartem 	} else if (dbus_message_is_method_call (message,
40742912Sartem 						"org.freedesktop.Hal.Device",
40752912Sartem 						"AddonIsReady")) {
40762912Sartem 		return addon_is_ready (connection, message, local_interface);
40772912Sartem 	} else if (dbus_message_is_method_call (message,
40782912Sartem 						"org.freedesktop.DBus.Introspectable",
40792912Sartem 						"Introspect")) {
40802912Sartem 		return do_introspect (connection, message, local_interface);
40812912Sartem 	} else {
40822912Sartem 		const char *interface;
40832912Sartem 		const char *udi;
40842912Sartem 		const char *method;
40852912Sartem 		const char *signature;
40862912Sartem 		HalDevice *d;
40872912Sartem 
40882912Sartem 		/* check for device-specific interfaces that individual objects may support */
40892912Sartem 
40902912Sartem 		udi = dbus_message_get_path (message);
40912912Sartem 		interface = dbus_message_get_interface (message);
40922912Sartem 		method = dbus_message_get_member (message);
40932912Sartem 		signature = dbus_message_get_signature (message);
40942912Sartem 
40952912Sartem 		d = NULL;
40962912Sartem 
40972912Sartem 		if (udi != NULL) {
40982912Sartem 			d = hal_device_store_find (hald_get_gdl (), udi);
40992912Sartem 			if (d == NULL)
41002912Sartem 				d = hal_device_store_find (hald_get_tdl (), udi);
41012912Sartem 		}
41022912Sartem 
41032912Sartem 		if (d != NULL && interface != NULL) {
41042912Sartem 			GSList *i;
41052912Sartem 
41062912Sartem 			for (i = helper_interface_handlers; i != NULL; i = g_slist_next (i)) {
41072912Sartem 				HelperInterfaceHandler *hih = i->data;
41082912Sartem 				if (strcmp (hih->udi, udi) == 0 &&
41092912Sartem 				    strcmp (hih->interface_name, interface) == 0) {
41102912Sartem 					DBusPendingCall *pending_call;
41112912Sartem 					DBusMessage *copy;
41122912Sartem 
41132912Sartem 					/*HAL_INFO (("forwarding method to connection 0x%x", hih->connection));*/
41142912Sartem 
41152912Sartem 					dbus_message_ref (message);
41162912Sartem 
41172912Sartem 					/* send a copy of the message */
41182912Sartem 					copy = dbus_message_copy (message);
41192912Sartem 					if (!dbus_connection_send_with_reply (hih->connection,
41202912Sartem 									      copy,
41212912Sartem 									      &pending_call,
41222912Sartem 									      /*-1*/ 8000)) {
41232912Sartem 						/* TODO: handle error */
41242912Sartem 					} else {
41252912Sartem 						/*HAL_INFO (("connection=%x message=%x", connection, message));*/
41262912Sartem 						dbus_pending_call_set_notify (pending_call,
41272912Sartem 									      reply_from_fwd_message,
41282912Sartem 									      (void *) message,
41292912Sartem 									      NULL);
41302912Sartem 					}
41312912Sartem 
41322912Sartem 					dbus_message_unref (copy);
41332912Sartem 
41342912Sartem 					return DBUS_HANDLER_RESULT_HANDLED;
41352912Sartem 				}
41362912Sartem 			}
41372912Sartem 		}
41382912Sartem 
41392912Sartem 		if (d != NULL && interface != NULL && method != NULL && signature != NULL) {
41402912Sartem 			GSList *interfaces;
41412912Sartem 			GSList *i;
41422912Sartem 
41432912Sartem 			interfaces = hal_device_property_get_strlist (d, "info.interfaces");
41442912Sartem 			for (i = interfaces; i != NULL; i = g_slist_next (i)) {
41452912Sartem 				const char *ifname = (const char *) i->data;
41462912Sartem 
41472912Sartem 				if (strcmp (ifname, interface) == 0) {
41482912Sartem 					guint num;
41492912Sartem 					GSList *method_names;
41502912Sartem 					char *s;
41512912Sartem 
41522912Sartem 					s = g_strdup_printf ("%s.method_names", interface);
41532912Sartem 					method_names = hal_device_property_get_strlist (d, s);
41542912Sartem 					g_free (s);
41552912Sartem 					for (i = method_names, num = 0; i != NULL; i = g_slist_next (i), num++) {
41562912Sartem 						const char *methodname = (const char *) i->data;
41572912Sartem 						if (strcmp (methodname, method) == 0) {
41582912Sartem 							const char *execpath;
41592912Sartem 							const char *sig;
41602912Sartem 
41612912Sartem 							s = g_strdup_printf ("%s.method_execpaths", interface);
41622912Sartem 							execpath = hal_device_property_get_strlist_elem (d, s, num);
41632912Sartem 							g_free (s);
41642912Sartem 							s = g_strdup_printf ("%s.method_signatures", interface);
41652912Sartem 							sig = hal_device_property_get_strlist_elem (d, s, num);
41662912Sartem 							g_free (s);
41672912Sartem 
41682912Sartem 							if (execpath != NULL && sig != NULL &&
41692912Sartem 							    strcmp (sig, signature) == 0) {
41702912Sartem 
41712912Sartem 								HAL_INFO (("OK for method '%s' with signature '%s' on interface '%s' for UDI '%s' and execpath '%s'", method, signature, interface, udi, execpath));
41722912Sartem 
41732912Sartem 								return hald_exec_method (d, connection, local_interface,
41742912Sartem 											 message, execpath);
41752912Sartem 							}
41762912Sartem 
41772912Sartem 						}
41782912Sartem 					}
41792912Sartem 				}
41802912Sartem 			}
41812912Sartem 
41822912Sartem 		}
41832912Sartem 	}
41842912Sartem 
41852912Sartem 	return osspec_filter_function (connection, message, user_data);
41862912Sartem }
41872912Sartem 
41882912Sartem 
41892912Sartem /** Message handler for method invocations. All invocations on any object
41902912Sartem  *  or interface is routed through this function.
41912912Sartem  *
41922912Sartem  *  @param  connection          D-BUS connection
41932912Sartem  *  @param  message             Message
41942912Sartem  *  @param  user_data           User data
41952912Sartem  *  @return                     What to do with the message
41962912Sartem  */
41972912Sartem DBusHandlerResult
hald_dbus_filter_function(DBusConnection * connection,DBusMessage * message,void * user_data)41982912Sartem hald_dbus_filter_function (DBusConnection * connection,
41992912Sartem 			   DBusMessage * message, void *user_data)
42002912Sartem {
42012912Sartem 	if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected") &&
42022912Sartem 	    strcmp (dbus_message_get_path (message), DBUS_PATH_LOCAL) == 0) {
42032912Sartem 
42042912Sartem 		/* this is a local message; e.g. from libdbus in this process */
42052912Sartem 
42062912Sartem 		HAL_INFO (("Got disconnected from the system message bus; "
42072912Sartem 			   "retrying to reconnect every 3000 ms"));
42082912Sartem 		dbus_connection_unref (dbus_connection);
42092912Sartem 		dbus_connection = NULL;
42102912Sartem 
42112912Sartem 		g_timeout_add (3000, reinit_dbus, NULL);
42122912Sartem 
42132912Sartem 	} else if (dbus_message_is_signal (message,
42142912Sartem 					   DBUS_INTERFACE_DBUS,
42152912Sartem 					   "NameOwnerChanged")) {
42162912Sartem 
42172912Sartem 		if (services_with_locks != NULL || services_with_claims != NULL)
42182912Sartem 			service_deleted (message);
42192912Sartem 	} else
42202912Sartem 		return hald_dbus_filter_handle_methods (connection, message, user_data, FALSE);
42212912Sartem 
42222912Sartem 	return DBUS_HANDLER_RESULT_HANDLED;
42232912Sartem }
42242912Sartem 
42252912Sartem 
42262912Sartem 
42272912Sartem static DBusHandlerResult
local_server_message_handler(DBusConnection * connection,DBusMessage * message,void * user_data)42282912Sartem local_server_message_handler (DBusConnection *connection,
42292912Sartem 			      DBusMessage *message,
42302912Sartem 			      void *user_data)
42312912Sartem {
42322912Sartem 	/*HAL_INFO (("local_server_message_handler: destination=%s obj_path=%s interface=%s method=%s",
42332912Sartem 		   dbus_message_get_destination (message),
42342912Sartem 		   dbus_message_get_path (message),
42352912Sartem 		   dbus_message_get_interface (message),
42362912Sartem 		   dbus_message_get_member (message)));*/
42372912Sartem 
42382912Sartem 	if (dbus_message_is_method_call (message, "org.freedesktop.DBus", "AddMatch")) {
42392912Sartem 		DBusMessage *reply;
42402912Sartem 
42412912Sartem 		/* cheat, and handle AddMatch since libhal will try to invoke this method */
42422912Sartem 		reply = dbus_message_new_method_return (message);
42432912Sartem 		if (reply == NULL)
42442912Sartem 			DIE (("No memory"));
42452912Sartem 		if (!dbus_connection_send (connection, reply, NULL))
42462912Sartem 			DIE (("No memory"));
42472912Sartem 		dbus_message_unref (reply);
42482912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
42492912Sartem 	} else if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected") &&
42502912Sartem 		   strcmp (dbus_message_get_path (message), DBUS_PATH_LOCAL) == 0) {
42512912Sartem 		GSList *i;
42522912Sartem 		GSList *j;
42532912Sartem 
42542912Sartem 		HAL_INFO (("Client to local_server was disconnected"));
42552912Sartem 
42562912Sartem 		for (i = helper_interface_handlers; i != NULL; i = j) {
42572912Sartem 			HelperInterfaceHandler *hih = i->data;
42582912Sartem 
42592912Sartem 			j = g_slist_next (i);
42602912Sartem 
42612912Sartem 			if (hih->connection == connection) {
42622912Sartem 				g_free (hih->interface_name);
42632912Sartem 				g_free (hih->introspection_xml);
42642912Sartem 				g_free (hih->udi);
42652912Sartem 				g_free (hih);
42663502Sartem 				helper_interface_handlers = g_slist_remove_link (helper_interface_handlers, i);
42672912Sartem 			}
42682912Sartem 		}
42692912Sartem 
42702912Sartem 		dbus_connection_unref (connection);
42712912Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
42722912Sartem 	} else if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_SIGNAL) {
42732912Sartem 		DBusMessage *copy;
42742912Sartem 
42752912Sartem 		/* it's a signal, just forward it onto the system message bus */
42762912Sartem 		copy = dbus_message_copy (message);
42772912Sartem 		if (dbus_connection != NULL) {
42782912Sartem 			dbus_connection_send (dbus_connection, copy, NULL);
42792912Sartem 		}
42802912Sartem 		dbus_message_unref (copy);
42812912Sartem 	} else {
42822912Sartem 		return hald_dbus_filter_handle_methods (connection, message, user_data, TRUE);
42832912Sartem 	}
42842912Sartem 
42852912Sartem 	return DBUS_HANDLER_RESULT_HANDLED;
42862912Sartem }
42872912Sartem 
42882912Sartem static void
local_server_unregister_handler(DBusConnection * connection,void * user_data)42892912Sartem local_server_unregister_handler (DBusConnection *connection, void *user_data)
42902912Sartem {
42912912Sartem 	HAL_INFO (("unregistered"));
42922912Sartem }
42932912Sartem 
42942912Sartem static void
local_server_handle_connection(DBusServer * server,DBusConnection * new_connection,void * data)42952912Sartem local_server_handle_connection (DBusServer *server,
42962912Sartem 			  DBusConnection *new_connection,
42972912Sartem 			  void *data)
42982912Sartem {
42992912Sartem 	DBusObjectPathVTable vtable = { &local_server_unregister_handler,
43002912Sartem 					&local_server_message_handler,
43012912Sartem 					NULL, NULL, NULL, NULL};
43022912Sartem 
43032912Sartem 	HAL_INFO (("%d: Got a connection", getpid ()));
43042912Sartem 	HAL_INFO (("dbus_connection_get_is_connected = %d", dbus_connection_get_is_connected (new_connection)));
43052912Sartem 
43062912Sartem 	/*dbus_connection_add_filter (new_connection, server_filter_function, NULL, NULL);*/
43072912Sartem 
43082912Sartem 	dbus_connection_register_fallback (new_connection,
43092912Sartem 					   "/org/freedesktop",
43102912Sartem 					   &vtable,
43112912Sartem 					   NULL);
43122912Sartem 	dbus_connection_ref (new_connection);
43132912Sartem 	dbus_connection_setup_with_g_main (new_connection, NULL);
43142912Sartem }
43152912Sartem 
43162912Sartem 
43172912Sartem static DBusServer *local_server = NULL;
43182912Sartem 
43192912Sartem char *
hald_dbus_local_server_addr(void)43202912Sartem hald_dbus_local_server_addr (void)
43212912Sartem {
43222912Sartem 	if (local_server == NULL)
43232912Sartem 		return NULL;
43242912Sartem 
43252912Sartem 	return dbus_server_get_address (local_server);
43262912Sartem }
43272912Sartem 
43282912Sartem gboolean
hald_dbus_local_server_init(void)43292912Sartem hald_dbus_local_server_init (void)
43302912Sartem {
43312912Sartem 	gboolean ret;
43322912Sartem 	DBusError error;
43332912Sartem 	char *server_addr;
43342912Sartem 
43352912Sartem 	ret = FALSE;
43362912Sartem 
43372912Sartem 	/* setup a server listening on a socket so we can do point to point
43382912Sartem 	 * connections for programs spawned by hald
43392912Sartem 	 */
43402912Sartem 	dbus_error_init (&error);
43412912Sartem 	if ((local_server = dbus_server_listen (HALD_DBUS_ADDRESS, &error)) == NULL) {
43422912Sartem 		HAL_ERROR (("Cannot create D-BUS server"));
43432912Sartem 		goto out;
43442912Sartem 	}
43452912Sartem 	server_addr = dbus_server_get_address (local_server);
43462912Sartem 	HAL_INFO (("local server is listening at %s", server_addr));
43472912Sartem 	dbus_free (server_addr);
43482912Sartem 	dbus_server_setup_with_g_main (local_server, NULL);
43492912Sartem 	dbus_server_set_new_connection_function (local_server, local_server_handle_connection, NULL, NULL);
43502912Sartem 
43512912Sartem 	ret = TRUE;
43522912Sartem 
43532912Sartem out:
43542912Sartem 	return ret;
43552912Sartem }
43562912Sartem 
43572912Sartem gboolean
hald_dbus_init(void)43582912Sartem hald_dbus_init (void)
43592912Sartem {
43602912Sartem 	DBusError dbus_error;
43612912Sartem 
43622912Sartem 	HAL_INFO (("entering"));
43632912Sartem 
43642912Sartem 	dbus_connection_set_change_sigpipe (TRUE);
43652912Sartem 
43662912Sartem 	dbus_error_init (&dbus_error);
43672912Sartem 	dbus_connection = dbus_bus_get (DBUS_BUS_SYSTEM, &dbus_error);
43682912Sartem 	if (dbus_connection == NULL) {
43692912Sartem 		HAL_ERROR (("dbus_bus_get(): %s", dbus_error.message));
43702912Sartem 		return FALSE;
43712912Sartem 	}
43722912Sartem 
43732912Sartem 	dbus_connection_setup_with_g_main (dbus_connection, NULL);
43742912Sartem 	dbus_connection_set_exit_on_disconnect (dbus_connection, FALSE);
43752912Sartem 
43762912Sartem 	dbus_bus_request_name (dbus_connection, "org.freedesktop.Hal",
43772912Sartem 				  0, &dbus_error);
43782912Sartem 	if (dbus_error_is_set (&dbus_error)) {
43792912Sartem 		HAL_ERROR (("dbus_bus_request_name(): %s",
43802912Sartem 			    dbus_error.message));
43812912Sartem 		return FALSE;
43822912Sartem 	}
43832912Sartem 
43842912Sartem 	dbus_connection_add_filter (dbus_connection, hald_dbus_filter_function, NULL, NULL);
43852912Sartem 
43862912Sartem 	dbus_bus_add_match (dbus_connection,
43872912Sartem 			    "type='signal'"
43882912Sartem 			    ",interface='"DBUS_INTERFACE_DBUS"'"
43892912Sartem 			    ",sender='"DBUS_SERVICE_DBUS"'"
43902912Sartem 			    ",member='NameOwnerChanged'",
43912912Sartem 			    NULL);
43922912Sartem 
43932912Sartem 	return TRUE;
43942912Sartem }
43952912Sartem 
43962912Sartem /** @} */
4397