hal/hald device.c, 1.16, 1.17 device.h, 1.10, 1.11 hald_dbus.c, 1.38, 1.39 util.c, 1.18, 1.19 util.h, 1.10, 1.11

David Zeuthen david at freedesktop.org
Tue Jul 12 20:38:04 PDT 2005


Update of /cvs/hal/hal/hald
In directory gabe:/tmp/cvs-serv463/hald

Modified Files:
	device.c device.h hald_dbus.c util.c util.h 
Log Message:
2005-07-12  David Zeuthen  <davidz at redhat.com>

        * hald/util.h: Add prototype for hal_util_helper_invoke_with_pipes

        * hald/util.c (hal_util_helper_invoke_with_pipes): New function (is
        based on hal_util_helper_invoke)
        (hal_util_helper_invoke): Use the with_pipes

        * hald/hald_dbus.c (hald_exec_method_cb): New function
        (hald_exec_method): New function
        (hald_dbus_filter_handle_methods): Check and handle methods on
        individual hal device objects

        * hald/device.h: Add prototype for hal_device_property_get_strlist_elem

        * hald/device.c (hal_device_property_get_strlist_elem): New function



Index: device.c
===================================================================
RCS file: /cvs/hal/hal/hald/device.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- device.c	28 Feb 2005 04:53:15 -0000	1.16
+++ device.c	13 Jul 2005 03:38:01 -0000	1.17
@@ -1090,6 +1090,25 @@
 		return NULL;
 }
 
+const char *
+hal_device_property_get_strlist_elem (HalDevice    *device,
+				      const char   *key,
+				      guint index)
+{
+	GSList *strlist;
+	GSList *i;
+
+	strlist = hal_device_property_get_strlist (device, key);
+	if (strlist == NULL)
+		return NULL;
+
+	i = g_slist_nth (strlist, index);
+	if (i == NULL)
+		return NULL;
+
+	return (const char *) i->data;
+}
+
 gboolean
 hal_device_property_strlist_append (HalDevice    *device,
 				    const char   *key,

Index: device.h
===================================================================
RCS file: /cvs/hal/hal/hald/device.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- device.h	31 Jan 2005 20:06:39 -0000	1.10
+++ device.h	13 Jul 2005 03:38:01 -0000	1.11
@@ -135,6 +135,9 @@
 					      const char   *key);
 GSList       *hal_device_property_get_strlist (HalDevice    *device,
 					       const char   *key);
+const char   *hal_device_property_get_strlist_elem (HalDevice    *device,
+						    const char   *key,
+						    guint index);
 
 
 

Index: hald_dbus.c
===================================================================
RCS file: /cvs/hal/hal/hald/hald_dbus.c,v
retrieving revision 1.38
retrieving revision 1.39
diff -u -d -r1.38 -r1.39
--- hald_dbus.c	8 Jul 2005 23:02:29 -0000	1.38
+++ hald_dbus.c	13 Jul 2005 03:38:01 -0000	1.39
@@ -2481,6 +2481,214 @@
 	return DBUS_HANDLER_RESULT_HANDLED;
 }
 
+static void
+hald_exec_method_cb (HalDevice *d, gboolean timed_out, gint return_code, 
+		     gpointer data1, gpointer data2, HalHelperData *helper_data)
+{
+	dbus_uint32_t result;
+	DBusMessage *reply;
+	DBusMessage *message;
+	DBusMessageIter iter;
+	int *stderr_fd;
+	char buf[512]; /* TODO: don't hardcode error message size */
+	char *exp_name;
+	char *exp_detail;
+
+	message = (DBusMessage *) data1;
+	stderr_fd = (int *) data2;
+
+	exp_name = NULL;
+	exp_detail = NULL;
+
+	/* read back possible error conditions from stderr */
+	if (stderr_fd != NULL) {
+		ssize_t num_read;
+
+		num_read = read (*stderr_fd, buf, sizeof (buf) - 2);
+		buf[sizeof (buf) - 2] = '\0';
+		buf[sizeof (buf) - 1] = '\0';
+		if (num_read > 0) {
+			char *p;
+			char *s;
+			p = buf;
+			for (s = p; *s != '\n' && *s != '\0'; s++)
+				;
+			if (*s != '\0') {
+				exp_name = g_strndup (p, s - p);
+				p = s + 1;
+				for (s = p; *s != '\n' && *s != '\0'; s++)
+					;
+				if (*s != '\0') {
+					exp_detail = g_strndup (p, s - p);
+				}
+			}
+		}
+	}
+
+	if (exp_name != NULL && exp_detail != NULL) {
+		HAL_INFO (("failed with '%s' '%s'", exp_name, exp_detail));
+
+		/* throw exception */
+
+		reply = dbus_message_new_error (message, exp_name, exp_detail);
+		if (reply == NULL)
+			DIE (("No memory"));
+		if (dbus_connection != NULL) {
+			if (!dbus_connection_send (dbus_connection, reply, NULL))
+				DIE (("No memory"));
+		}
+		dbus_message_unref (reply);
+
+	} else {
+		result = (dbus_uint32_t) return_code;
+
+		reply = dbus_message_new_method_return (message);
+		if (reply == NULL)
+			DIE (("No memory"));
+		
+		dbus_message_iter_init_append (reply, &iter);
+		dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &result);
+		
+		if (dbus_connection != NULL) {
+			if (!dbus_connection_send (dbus_connection, reply, NULL))
+				DIE (("No memory"));
+		}
+
+		dbus_message_unref (reply);
+	}
+
+	dbus_message_unref (message);
+	g_free (stderr_fd);
+	g_free (exp_name);
+	g_free (exp_detail);
+}
+
+static DBusHandlerResult
+hald_exec_method (HalDevice *d, DBusConnection *connection, DBusMessage *message, const char *execpath)
+{
+	int type;
+	char *stdin;
+	GString *stdin_str;
+	DBusMessageIter iter;
+	int stdin_fd;
+	int *stderr_fd;
+
+	/* TODO: check that sender is e.g. at console */
+/*
+	if (!sender_has_privileges (connection, message)) {
+		raise_permission_denied (connection, message, "not privileged");
+		return DBUS_HANDLER_RESULT_HANDLED;
+	}
+*/
+
+	stdin_str = g_string_sized_new (256); /* reasonable default size for passing params; can grow */
+
+	/* prepare stdin with parameters */
+	dbus_message_iter_init (message, &iter);
+	while ((type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID) {
+		switch (type) {
+		case DBUS_TYPE_BYTE:
+		{
+			unsigned char value;
+			dbus_message_iter_get_basic (&iter, &value);
+			g_string_append_printf (stdin_str, "%u", value);
+			break;
+		}
+		case DBUS_TYPE_INT16:
+		{
+			dbus_int16_t value;
+			dbus_message_iter_get_basic (&iter, &value);
+			g_string_append_printf (stdin_str, "%d", value);
+			break;
+		}
+		case DBUS_TYPE_UINT16:
+		{
+			dbus_uint16_t value;
+			dbus_message_iter_get_basic (&iter, &value);
+			g_string_append_printf (stdin_str, "%u", value);
+			break;
+		}
+		case DBUS_TYPE_INT32:
+		{
+			dbus_int32_t value;
+			dbus_message_iter_get_basic (&iter, &value);
+			g_string_append_printf (stdin_str, "%d", value);
+			break;
+		}
+		case DBUS_TYPE_UINT32:
+		{
+			dbus_uint32_t value;
+			dbus_message_iter_get_basic (&iter, &value);
+			g_string_append_printf (stdin_str, "%u", value);
+			break;
+		}
+		case DBUS_TYPE_INT64:
+		{
+			dbus_int64_t value;
+			dbus_message_iter_get_basic (&iter, &value);
+			g_string_append_printf (stdin_str, "%lld", value);
+			break;
+		}
+		case DBUS_TYPE_UINT64:
+		{
+			dbus_uint64_t value;
+			dbus_message_iter_get_basic (&iter, &value);
+			g_string_append_printf (stdin_str, "%llu", value);
+			break;
+		}
+		case DBUS_TYPE_DOUBLE:
+		{
+			double value;
+			dbus_message_iter_get_basic (&iter, &value);
+			g_string_append_printf (stdin_str, "%g", value);
+			break;
+		}
+		case DBUS_TYPE_BOOLEAN:
+		{
+			dbus_bool_t value;
+			dbus_message_iter_get_basic (&iter, &value);
+			g_string_append (stdin_str, value ? "true" : "false");
+			break;
+		}
+		case DBUS_TYPE_STRING:
+		{
+			char *value;
+			dbus_message_iter_get_basic (&iter, &value);
+			g_string_append (stdin_str, value);
+			break;
+		}
+
+		default:
+			goto error;
+		}
+
+		g_string_append_c (stdin_str, '\n');
+		
+		dbus_message_iter_next (&iter);
+	}
+
+	stdin = g_string_free (stdin_str, FALSE);
+
+	stderr_fd = (int *) g_new0 (int, 1);
+
+	/* no timeout */
+	if (hal_util_helper_invoke_with_pipes (execpath, NULL, d, 
+					       (gpointer) message, (gpointer) stderr_fd, 
+					       hald_exec_method_cb, 0, &stdin_fd, NULL, stderr_fd) != NULL) {
+		write (stdin_fd, stdin, strlen (stdin));
+		close (stdin_fd);
+	}
+
+	dbus_message_ref (message);
+
+	g_free (stdin);
+
+	return DBUS_HANDLER_RESULT_HANDLED;
+
+error:
+	g_string_free (stdin_str, TRUE);
+	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
 
 static DBusHandlerResult
 hald_dbus_filter_handle_methods (DBusConnection *connection, DBusMessage *message, 
@@ -2630,11 +2838,76 @@
 						"org.freedesktop.Hal.Device",
 						"EmitCondition")) {
 		return device_emit_condition (connection, message, local_interface);
-	} else
-		osspec_filter_function (connection, message, user_data);
+	} else {
+		const char *interface;
+		const char *udi;
+		const char *method;
+		const char *signature;
+		HalDevice *d;
 
-	return DBUS_HANDLER_RESULT_HANDLED;
+		/* check for device-specific interfaces that individual objects may support */
+
+		udi = dbus_message_get_path (message);
+		interface = dbus_message_get_interface (message);
+		method = dbus_message_get_member (message);
+		signature = dbus_message_get_signature (message);
+
+		d = NULL;
+
+		if (method != NULL) {
+			d = hal_device_store_find (hald_get_gdl (), udi);
+			if (d == NULL)
+				d = hal_device_store_find (hald_get_tdl (), udi);
+		}
+
+		if (d != NULL && interface != NULL && method != NULL && signature != NULL) {
+			GSList *interfaces;
+			GSList *i;
+
+			interfaces = hal_device_property_get_strlist (d, "info.interfaces");
+			for (i = interfaces; i != NULL; i = g_slist_next (i)) {
+				const char *ifname = (const char *) i->data;
+
+				if (strcmp (ifname, interface) == 0) {
+					guint num;
+					GSList *method_names;
+					char *s;
+
+					s = g_strdup_printf ("%s.method_names", interface);
+					method_names = hal_device_property_get_strlist (d, s);
+					g_free (s);
+					for (i = method_names, num = 0; i != NULL; i = g_slist_next (i), num++) {
+						const char *methodname = (const char *) i->data;
+						if (strcmp (methodname, method) == 0) {
+							const char *execpath;
+							const char *sig;
+
+							s = g_strdup_printf ("%s.method_execpaths", interface);
+							execpath = hal_device_property_get_strlist_elem (d, s, num);
+							g_free (s);
+							s = g_strdup_printf ("%s.method_signatures", interface);
+							sig = hal_device_property_get_strlist_elem (d, s, num);
+							g_free (s);
+							
+							if (execpath != NULL && sig != NULL && 
+							    strcmp (sig, signature) == 0) {
+
+								HAL_INFO (("OK for method '%s' with signature '%s' on interface '%s' for UDI '%s' and execpath '%s'", method, signature, interface, udi, execpath));
+
+								return hald_exec_method (d, connection, message, execpath);
+							}
+							
+						}
+					}
+				}
+			}
+			
+		}
+	}
+		
+	return osspec_filter_function (connection, message, user_data);
 }
+       
 
 /** Message handler for method invocations. All invocations on any object
  *  or interface is routed through this function.
@@ -2648,12 +2921,10 @@
 hald_dbus_filter_function (DBusConnection * connection,
 			   DBusMessage * message, void *user_data)
 {
-	/*
-	HAL_INFO (("obj_path=%s interface=%s method=%s", 
+	/*HAL_INFO (("obj_path=%s interface=%s method=%s", 
 		   dbus_message_get_path(message), 
 		   dbus_message_get_interface(message),
-		   dbus_message_get_member(message)));
-	*/
+		   dbus_message_get_member(message)));*/
 
 	if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected") &&
 	    strcmp (dbus_message_get_path (message), DBUS_PATH_LOCAL) == 0) {

Index: util.c
===================================================================
RCS file: /cvs/hal/hal/hald/util.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- util.c	27 Jun 2005 19:13:03 -0000	1.18
+++ util.c	13 Jul 2005 03:38:01 -0000	1.19
@@ -528,6 +528,14 @@
 hal_util_helper_invoke (const gchar *command_line, gchar **extra_env, HalDevice *d, 
 			gpointer data1, gpointer data2, HalHelperTerminatedCB cb, guint timeout)
 {
+	return hal_util_helper_invoke_with_pipes (command_line, extra_env, d, data1, data2, cb, timeout, NULL, NULL, NULL);
+}
+
+HalHelperData *
+hal_util_helper_invoke_with_pipes (const gchar *command_line, gchar **extra_env, HalDevice *d, 
+				   gpointer data1, gpointer data2, HalHelperTerminatedCB cb, guint timeout,
+				   int *standard_input, int *standard_output, int *standard_error)
+{
 	HalHelperData *ed;
 	gint argc;
 	gchar **argv;
@@ -585,14 +593,17 @@
 		ed = NULL;
 	} else {
 		err = NULL;
-		if (!g_spawn_async (NULL, 
-				    argv, 
-				    envp, 
-				    G_SPAWN_DO_NOT_REAP_CHILD|G_SPAWN_SEARCH_PATH,
-				    NULL,
-				    NULL,
-				    &ed->pid,
-				    &err)) {
+		if (!g_spawn_async_with_pipes (NULL, 
+					       argv, 
+					       envp, 
+					       G_SPAWN_DO_NOT_REAP_CHILD|G_SPAWN_SEARCH_PATH,
+					       NULL,
+					       NULL,
+					       &ed->pid,
+					       standard_input,
+					       standard_output,
+					       standard_error,
+					       &err)) {
 			HAL_ERROR (("Couldn't spawn '%s' err=%s!", command_line, err->message));
 			g_error_free (err);
 			g_free (ed);

Index: util.h
===================================================================
RCS file: /cvs/hal/hal/hald/util.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- util.h	23 Jun 2005 14:50:04 -0000	1.10
+++ util.h	13 Jul 2005 03:38:01 -0000	1.11
@@ -103,6 +103,11 @@
 HalHelperData  *hal_util_helper_invoke (const gchar *command_line, gchar **extra_env, HalDevice *d, 
 					gpointer data1, gpointer data2, HalHelperTerminatedCB cb, guint timeout);
 
+HalHelperData  *hal_util_helper_invoke_with_pipes (const gchar *command_line, gchar **extra_env, HalDevice *d, 
+						   gpointer data1, gpointer data2, HalHelperTerminatedCB cb, 
+						   guint timeout,
+						   int *standard_input, int *standard_output, int *standard_error);
+
 void hal_util_terminate_helper (HalHelperData *helper_data);
 
 gchar **hal_util_dup_strv_from_g_slist (GSList *strlist);




More information about the hal-commit mailing list