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