118c2aff7Sartem /*************************************************************************** 218c2aff7Sartem * CVSID: $Id$ 318c2aff7Sartem * 418c2aff7Sartem * hald_runner.c - Interface to the hal runner helper daemon 518c2aff7Sartem * 618c2aff7Sartem * Copyright (C) 2006 Sjoerd Simons, <sjoerd@luon.net> 718c2aff7Sartem * 818c2aff7Sartem * Licensed under the Academic Free License version 2.1 918c2aff7Sartem * 1018c2aff7Sartem * This program is free software; you can redistribute it and/or modify 1118c2aff7Sartem * it under the terms of the GNU General Public License as published by 1218c2aff7Sartem * the Free Software Foundation; either version 2 of the License, or 1318c2aff7Sartem * (at your option) any later version. 1418c2aff7Sartem * 1518c2aff7Sartem * This program is distributed in the hope that it will be useful, 1618c2aff7Sartem * but WITHOUT ANY WARRANTY; without even the implied warranty of 1718c2aff7Sartem * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1818c2aff7Sartem * GNU General Public License for more details. 1918c2aff7Sartem * 2018c2aff7Sartem * You should have received a copy of the GNU General Public License 2118c2aff7Sartem * along with this program; if not, write to the Free Software 2218c2aff7Sartem * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 2318c2aff7Sartem * 2418c2aff7Sartem **************************************************************************/ 2518c2aff7Sartem 2618c2aff7Sartem #ifdef HAVE_CONFIG_H 2718c2aff7Sartem # include <config.h> 2818c2aff7Sartem #endif 2918c2aff7Sartem 3018c2aff7Sartem #include <sys/utsname.h> 3118c2aff7Sartem #include <stdio.h> 3218c2aff7Sartem 3318c2aff7Sartem #include <glib.h> 3418c2aff7Sartem #include <dbus/dbus.h> 3518c2aff7Sartem #include <dbus/dbus-glib-lowlevel.h> 3618c2aff7Sartem 3718c2aff7Sartem #include "hald.h" 3818c2aff7Sartem #include "util.h" 3918c2aff7Sartem #include "logger.h" 4018c2aff7Sartem #include "hald_dbus.h" 4118c2aff7Sartem #include "hald_runner.h" 4218c2aff7Sartem 4318c2aff7Sartem typedef struct { 4418c2aff7Sartem HalDevice *d; 4518c2aff7Sartem HalRunTerminatedCB cb; 4618c2aff7Sartem gpointer data1; 4718c2aff7Sartem gpointer data2; 4818c2aff7Sartem } HelperData; 4918c2aff7Sartem 5018c2aff7Sartem #define DBUS_SERVER_ADDRESS "unix:tmpdir=" HALD_SOCKET_DIR 5118c2aff7Sartem 5218c2aff7Sartem static DBusConnection *runner_connection = NULL; 5318c2aff7Sartem 5418c2aff7Sartem typedef struct 5518c2aff7Sartem { 5618c2aff7Sartem GPid pid; 5718c2aff7Sartem HalDevice *device; 5818c2aff7Sartem HalRunTerminatedCB cb; 5918c2aff7Sartem gpointer data1; 6018c2aff7Sartem gpointer data2; 6118c2aff7Sartem } RunningProcess; 6218c2aff7Sartem 6318c2aff7Sartem /* mapping from PID to RunningProcess */ 6418c2aff7Sartem static GHashTable *running_processes; 6518c2aff7Sartem 6618c2aff7Sartem static gboolean 6718c2aff7Sartem rprd_foreach (gpointer key, 6818c2aff7Sartem gpointer value, 6918c2aff7Sartem gpointer user_data) 7018c2aff7Sartem { 7118c2aff7Sartem gboolean remove = FALSE; 7218c2aff7Sartem RunningProcess *rp = value; 7318c2aff7Sartem HalDevice *device = user_data; 7418c2aff7Sartem 7518c2aff7Sartem if (rp->device == device) { 7618c2aff7Sartem remove = TRUE; 7718c2aff7Sartem g_free (rp); 7818c2aff7Sartem } 7918c2aff7Sartem 8018c2aff7Sartem return remove; 8118c2aff7Sartem } 8218c2aff7Sartem 8318c2aff7Sartem static void 8418c2aff7Sartem running_processes_remove_device (HalDevice *device) 8518c2aff7Sartem { 8618c2aff7Sartem g_hash_table_foreach_remove (running_processes, rprd_foreach, device); 8718c2aff7Sartem } 8818c2aff7Sartem 8918c2aff7Sartem void 9018c2aff7Sartem runner_device_finalized (HalDevice *device) 9118c2aff7Sartem { 9218c2aff7Sartem running_processes_remove_device (device); 9318c2aff7Sartem } 9418c2aff7Sartem 9518c2aff7Sartem 9618c2aff7Sartem static DBusHandlerResult 9718c2aff7Sartem runner_server_message_handler (DBusConnection *connection, 9818c2aff7Sartem DBusMessage *message, 9918c2aff7Sartem void *user_data) 10018c2aff7Sartem { 10118c2aff7Sartem 10218c2aff7Sartem /*HAL_INFO (("runner_server_message_handler: destination=%s obj_path=%s interface=%s method=%s", 10318c2aff7Sartem dbus_message_get_destination (message), 10418c2aff7Sartem dbus_message_get_path (message), 10518c2aff7Sartem dbus_message_get_interface (message), 10618c2aff7Sartem dbus_message_get_member (message)));*/ 10718c2aff7Sartem if (dbus_message_is_signal (message, 10818c2aff7Sartem "org.freedesktop.HalRunner", 10918c2aff7Sartem "StartedProcessExited")) { 11018c2aff7Sartem dbus_uint64_t dpid; 11118c2aff7Sartem DBusError error; 11218c2aff7Sartem dbus_error_init (&error); 11318c2aff7Sartem if (dbus_message_get_args (message, &error, 11418c2aff7Sartem DBUS_TYPE_INT64, &dpid, 11518c2aff7Sartem DBUS_TYPE_INVALID)) { 11618c2aff7Sartem RunningProcess *rp; 11718c2aff7Sartem GPid pid; 11818c2aff7Sartem 11918c2aff7Sartem pid = (GPid) dpid; 12018c2aff7Sartem 12118c2aff7Sartem /*HAL_INFO (("Previously started process with pid %d exited", pid));*/ 12218c2aff7Sartem rp = g_hash_table_lookup (running_processes, (gpointer) pid); 12318c2aff7Sartem if (rp != NULL) { 12418c2aff7Sartem rp->cb (rp->device, 0, 0, NULL, rp->data1, rp->data2); 12518c2aff7Sartem g_hash_table_remove (running_processes, (gpointer) pid); 12618c2aff7Sartem g_free (rp); 12718c2aff7Sartem } 12818c2aff7Sartem } 12918c2aff7Sartem } 13018c2aff7Sartem return DBUS_HANDLER_RESULT_HANDLED; 13118c2aff7Sartem } 13218c2aff7Sartem 13318c2aff7Sartem static void 13418c2aff7Sartem runner_server_unregister_handler (DBusConnection *connection, void *user_data) 13518c2aff7Sartem { 13618c2aff7Sartem HAL_INFO (("unregistered")); 13718c2aff7Sartem } 13818c2aff7Sartem 13918c2aff7Sartem 14018c2aff7Sartem static void 14118c2aff7Sartem handle_connection(DBusServer *server, 14218c2aff7Sartem DBusConnection *new_connection, 14318c2aff7Sartem void *data) 14418c2aff7Sartem { 14518c2aff7Sartem 14618c2aff7Sartem if (runner_connection == NULL) { 14718c2aff7Sartem DBusObjectPathVTable vtable = { &runner_server_unregister_handler, 14818c2aff7Sartem &runner_server_message_handler, 14918c2aff7Sartem NULL, NULL, NULL, NULL}; 15018c2aff7Sartem 15118c2aff7Sartem runner_connection = new_connection; 15218c2aff7Sartem dbus_connection_ref (new_connection); 15318c2aff7Sartem dbus_connection_setup_with_g_main (new_connection, NULL); 15418c2aff7Sartem 15518c2aff7Sartem dbus_connection_register_fallback (new_connection, 15618c2aff7Sartem "/org/freedesktop", 15718c2aff7Sartem &vtable, 15818c2aff7Sartem NULL); 15918c2aff7Sartem 16018c2aff7Sartem /* dbus_server_unref(server); */ 16118c2aff7Sartem 16218c2aff7Sartem } 16318c2aff7Sartem } 16418c2aff7Sartem 16518c2aff7Sartem static void 16618c2aff7Sartem runner_died(GPid pid, gint status, gpointer data) { 16718c2aff7Sartem g_spawn_close_pid (pid); 16818c2aff7Sartem DIE (("Runner died")); 16918c2aff7Sartem } 17018c2aff7Sartem 17118c2aff7Sartem gboolean 17218c2aff7Sartem hald_runner_start_runner(void) 17318c2aff7Sartem { 17418c2aff7Sartem DBusServer *server = NULL; 17518c2aff7Sartem DBusError err; 17618c2aff7Sartem GError *error = NULL; 17718c2aff7Sartem GPid pid; 17818c2aff7Sartem char *argv[] = { NULL, NULL}; 17918c2aff7Sartem char *env[] = { NULL, NULL, NULL, NULL}; 18018c2aff7Sartem const char *hald_runner_path; 18118c2aff7Sartem char *server_addr; 18218c2aff7Sartem 18318c2aff7Sartem running_processes = g_hash_table_new (g_direct_hash, g_direct_equal); 18418c2aff7Sartem 18518c2aff7Sartem dbus_error_init(&err); 18618c2aff7Sartem server = dbus_server_listen(DBUS_SERVER_ADDRESS, &err); 18718c2aff7Sartem if (server == NULL) { 18818c2aff7Sartem HAL_ERROR (("Cannot create D-BUS server for the runner")); 18918c2aff7Sartem goto error; 19018c2aff7Sartem } 19118c2aff7Sartem 19218c2aff7Sartem dbus_server_setup_with_g_main(server, NULL); 19318c2aff7Sartem dbus_server_set_new_connection_function(server, handle_connection, 19418c2aff7Sartem NULL, NULL); 19518c2aff7Sartem 19618c2aff7Sartem 19718c2aff7Sartem argv[0] = "hald-runner"; 19818c2aff7Sartem server_addr = dbus_server_get_address (server); 19918c2aff7Sartem env[0] = g_strdup_printf("HALD_RUNNER_DBUS_ADDRESS=%s", server_addr); 20018c2aff7Sartem dbus_free (server_addr); 20118c2aff7Sartem hald_runner_path = g_getenv("HALD_RUNNER_PATH"); 20218c2aff7Sartem if (hald_runner_path != NULL) { 20318c2aff7Sartem env[1] = g_strdup_printf ("PATH=%s:" PACKAGE_LIBEXEC_DIR ":" PACKAGE_SCRIPT_DIR ":" PACKAGE_BIN_DIR, hald_runner_path); 20418c2aff7Sartem } else { 20518c2aff7Sartem env[1] = g_strdup_printf ("PATH=" PACKAGE_LIBEXEC_DIR ":" PACKAGE_SCRIPT_DIR ":" PACKAGE_BIN_DIR); 20618c2aff7Sartem } 20718c2aff7Sartem 20818c2aff7Sartem /*env[2] = "DBUS_VERBOSE=1";*/ 20918c2aff7Sartem 21018c2aff7Sartem 21118c2aff7Sartem if (!g_spawn_async(NULL, argv, env, G_SPAWN_DO_NOT_REAP_CHILD|G_SPAWN_SEARCH_PATH, 21218c2aff7Sartem NULL, NULL, &pid, &error)) { 21318c2aff7Sartem HAL_ERROR (("Could not spawn runner : '%s'", error->message)); 21418c2aff7Sartem g_error_free (error); 21518c2aff7Sartem goto error; 21618c2aff7Sartem } 21718c2aff7Sartem g_free(env[0]); 21818c2aff7Sartem g_free(env[1]); 21918c2aff7Sartem 22018c2aff7Sartem HAL_INFO (("Runner has pid %d", pid)); 22118c2aff7Sartem 22218c2aff7Sartem g_child_watch_add(pid, runner_died, NULL); 22318c2aff7Sartem while (runner_connection == NULL) { 22418c2aff7Sartem /* Wait for the runner */ 22518c2aff7Sartem g_main_context_iteration(NULL, TRUE); 22618c2aff7Sartem } 22718c2aff7Sartem return TRUE; 22818c2aff7Sartem 22918c2aff7Sartem error: 23018c2aff7Sartem if (server != NULL) 23118c2aff7Sartem dbus_server_unref(server); 23218c2aff7Sartem return FALSE; 23318c2aff7Sartem } 23418c2aff7Sartem 23518c2aff7Sartem static gboolean 23618c2aff7Sartem add_property_to_msg (HalDevice *device, HalProperty *property, 23718c2aff7Sartem gpointer user_data) 23818c2aff7Sartem { 23918c2aff7Sartem char *prop_upper, *value; 24018c2aff7Sartem char *c; 24118c2aff7Sartem gchar *env; 24218c2aff7Sartem DBusMessageIter *iter = (DBusMessageIter *)user_data; 24318c2aff7Sartem 24418c2aff7Sartem prop_upper = g_ascii_strup (hal_property_get_key (property), -1); 24518c2aff7Sartem 24618c2aff7Sartem /* periods aren't valid in the environment, so replace them with 24718c2aff7Sartem * underscores. */ 24818c2aff7Sartem for (c = prop_upper; *c; c++) { 24918c2aff7Sartem if (*c == '.') 25018c2aff7Sartem *c = '_'; 25118c2aff7Sartem } 25218c2aff7Sartem 25318c2aff7Sartem value = hal_property_to_string (property); 25418c2aff7Sartem env = g_strdup_printf ("HAL_PROP_%s=%s", prop_upper, value); 25518c2aff7Sartem dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &env); 25618c2aff7Sartem 25718c2aff7Sartem g_free (env); 25818c2aff7Sartem g_free (value); 25918c2aff7Sartem g_free (prop_upper); 26018c2aff7Sartem 26118c2aff7Sartem return TRUE; 26218c2aff7Sartem } 26318c2aff7Sartem 26418c2aff7Sartem static void 26518c2aff7Sartem add_env(DBusMessageIter *iter, const gchar *key, const gchar *value) { 26618c2aff7Sartem gchar *env; 26718c2aff7Sartem env = g_strdup_printf ("%s=%s", key, value); 26818c2aff7Sartem dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &env); 26918c2aff7Sartem g_free(env); 27018c2aff7Sartem } 27118c2aff7Sartem 27218c2aff7Sartem static void 27318c2aff7Sartem add_basic_env(DBusMessageIter *iter, const gchar *udi) { 27418c2aff7Sartem struct utsname un; 27518c2aff7Sartem char *server_addr; 27618c2aff7Sartem 27718c2aff7Sartem if (hald_is_verbose) { 27818c2aff7Sartem add_env(iter, "HALD_VERBOSE", "1"); 27918c2aff7Sartem } 28018c2aff7Sartem if (hald_is_initialising) { 28118c2aff7Sartem add_env(iter, "HALD_STARTUP", "1"); 28218c2aff7Sartem } 28318c2aff7Sartem if (hald_use_syslog) { 28418c2aff7Sartem add_env(iter, "HALD_USE_SYSLOG", "1"); 28518c2aff7Sartem } 28618c2aff7Sartem add_env(iter, "UDI", udi); 28718c2aff7Sartem server_addr = hald_dbus_local_server_addr(); 28818c2aff7Sartem add_env(iter, "HALD_DIRECT_ADDR", server_addr); 28918c2aff7Sartem dbus_free (server_addr); 29018c2aff7Sartem #ifdef HAVE_POLKIT 29118c2aff7Sartem add_env(iter, "HAVE_POLKIT", "1"); 29218c2aff7Sartem #endif 29318c2aff7Sartem 294d2ec54f7Sphitran if (uname(&un) >= 0) { 29518c2aff7Sartem char *sysname; 29618c2aff7Sartem 29718c2aff7Sartem sysname = g_ascii_strdown(un.sysname, -1); 29818c2aff7Sartem add_env(iter, "HALD_UNAME_S", sysname); 29918c2aff7Sartem g_free(sysname); 30018c2aff7Sartem } 30118c2aff7Sartem } 30218c2aff7Sartem 30318c2aff7Sartem static void 30418c2aff7Sartem add_extra_env(DBusMessageIter *iter, gchar **env) { 30518c2aff7Sartem int i; 30618c2aff7Sartem if (env != NULL) for (i = 0; env[i] != NULL; i++) { 30718c2aff7Sartem dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &env[i]); 30818c2aff7Sartem } 30918c2aff7Sartem } 31018c2aff7Sartem 31118c2aff7Sartem static gboolean 31218c2aff7Sartem add_command(DBusMessageIter *iter, const gchar *command_line) { 31318c2aff7Sartem gint argc; 31418c2aff7Sartem gint x; 31518c2aff7Sartem char **argv; 31618c2aff7Sartem GError *err = NULL; 31718c2aff7Sartem DBusMessageIter array_iter; 31818c2aff7Sartem 31918c2aff7Sartem if (!g_shell_parse_argv(command_line, &argc, &argv, &err)) { 32018c2aff7Sartem HAL_ERROR (("Error parsing commandline '%s': %s", 32118c2aff7Sartem command_line, err->message)); 32218c2aff7Sartem g_error_free (err); 32318c2aff7Sartem return FALSE; 32418c2aff7Sartem } 32518c2aff7Sartem if (!dbus_message_iter_open_container(iter, 32618c2aff7Sartem DBUS_TYPE_ARRAY, 32718c2aff7Sartem DBUS_TYPE_STRING_AS_STRING, 32818c2aff7Sartem &array_iter)) 32918c2aff7Sartem DIE (("No memory")); 33018c2aff7Sartem for (x = 0 ; argv[x] != NULL; x++) { 33118c2aff7Sartem dbus_message_iter_append_basic(&array_iter, DBUS_TYPE_STRING, &argv[x]); 33218c2aff7Sartem } 33318c2aff7Sartem dbus_message_iter_close_container(iter, &array_iter); 33418c2aff7Sartem 33518c2aff7Sartem g_strfreev(argv); 33618c2aff7Sartem return TRUE; 33718c2aff7Sartem } 33818c2aff7Sartem 33918c2aff7Sartem static gboolean 34018c2aff7Sartem add_first_part(DBusMessageIter *iter, HalDevice *device, 34118c2aff7Sartem const gchar *command_line, char **extra_env) { 34218c2aff7Sartem DBusMessageIter array_iter; 34318c2aff7Sartem const char *udi; 34418c2aff7Sartem 34518c2aff7Sartem udi = hal_device_get_udi(device); 34618c2aff7Sartem dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &udi); 34718c2aff7Sartem 34818c2aff7Sartem dbus_message_iter_open_container(iter, 34918c2aff7Sartem DBUS_TYPE_ARRAY, 35018c2aff7Sartem DBUS_TYPE_STRING_AS_STRING, 35118c2aff7Sartem &array_iter); 35218c2aff7Sartem hal_device_property_foreach (device, add_property_to_msg, &array_iter); 35318c2aff7Sartem add_basic_env(&array_iter, udi); 35418c2aff7Sartem add_extra_env(&array_iter, extra_env); 35518c2aff7Sartem dbus_message_iter_close_container(iter, &array_iter); 35618c2aff7Sartem 35718c2aff7Sartem if (!add_command(iter, command_line)) { 35818c2aff7Sartem return FALSE; 35918c2aff7Sartem } 36018c2aff7Sartem return TRUE; 36118c2aff7Sartem } 36218c2aff7Sartem 36318c2aff7Sartem /* Start a helper, returns true on a successfull start */ 36418c2aff7Sartem gboolean 36518c2aff7Sartem hald_runner_start (HalDevice *device, const gchar *command_line, char **extra_env, 36618c2aff7Sartem HalRunTerminatedCB cb, gpointer data1, gpointer data2) 36718c2aff7Sartem { 36818c2aff7Sartem DBusMessage *msg, *reply; 36918c2aff7Sartem DBusError err; 37018c2aff7Sartem DBusMessageIter iter; 37118c2aff7Sartem 37218c2aff7Sartem dbus_error_init(&err); 37318c2aff7Sartem msg = dbus_message_new_method_call("org.freedesktop.HalRunner", 37418c2aff7Sartem "/org/freedesktop/HalRunner", 37518c2aff7Sartem "org.freedesktop.HalRunner", 37618c2aff7Sartem "Start"); 37718c2aff7Sartem if (msg == NULL) 37818c2aff7Sartem DIE(("No memory")); 37918c2aff7Sartem dbus_message_iter_init_append(msg, &iter); 38018c2aff7Sartem 38118c2aff7Sartem if (!add_first_part(&iter, device, command_line, extra_env)) 38218c2aff7Sartem goto error; 38318c2aff7Sartem 38418c2aff7Sartem /* Wait for the reply, should be almost instantanious */ 38518c2aff7Sartem reply = 38618c2aff7Sartem dbus_connection_send_with_reply_and_block(runner_connection, 38718c2aff7Sartem msg, -1, &err); 38818c2aff7Sartem if (reply) { 38918c2aff7Sartem gboolean ret = 39018c2aff7Sartem (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_METHOD_RETURN); 39118c2aff7Sartem 39218c2aff7Sartem if (ret) { 39318c2aff7Sartem dbus_int64_t pid_from_runner; 39418c2aff7Sartem if (dbus_message_get_args (reply, &err, 39518c2aff7Sartem DBUS_TYPE_INT64, &pid_from_runner, 39618c2aff7Sartem DBUS_TYPE_INVALID)) { 39718c2aff7Sartem if (cb != NULL) { 39818c2aff7Sartem RunningProcess *rp; 39918c2aff7Sartem rp = g_new0 (RunningProcess, 1); 40018c2aff7Sartem rp->pid = (GPid) pid_from_runner; 40118c2aff7Sartem rp->cb = cb; 40218c2aff7Sartem rp->device = device; 40318c2aff7Sartem rp->data1 = data1; 40418c2aff7Sartem rp->data2 = data2; 40518c2aff7Sartem 40618c2aff7Sartem g_hash_table_insert (running_processes, (gpointer) rp->pid, rp); 40718c2aff7Sartem } 40818c2aff7Sartem } else { 40918c2aff7Sartem HAL_ERROR (("Error extracting out_pid from runner's Start()")); 41018c2aff7Sartem } 41118c2aff7Sartem } 41218c2aff7Sartem 41318c2aff7Sartem dbus_message_unref(reply); 41418c2aff7Sartem dbus_message_unref(msg); 41518c2aff7Sartem return ret; 41618c2aff7Sartem } 41718c2aff7Sartem 41818c2aff7Sartem error: 41918c2aff7Sartem dbus_message_unref(msg); 42018c2aff7Sartem return FALSE; 42118c2aff7Sartem } 42218c2aff7Sartem 42318c2aff7Sartem static void 42418c2aff7Sartem call_notify(DBusPendingCall *pending, void *user_data) 42518c2aff7Sartem { 42618c2aff7Sartem HelperData *hb = (HelperData *)user_data; 42718c2aff7Sartem dbus_uint32_t exitt = HALD_RUN_SUCCESS; 42818c2aff7Sartem dbus_int32_t return_code = 0; 42918c2aff7Sartem DBusMessage *m; 43018c2aff7Sartem GArray *error = NULL; 43118c2aff7Sartem DBusMessageIter iter; 43218c2aff7Sartem 43318c2aff7Sartem error = g_array_new(TRUE, FALSE, sizeof(char *)); 43418c2aff7Sartem 43518c2aff7Sartem m = dbus_pending_call_steal_reply(pending); 43618c2aff7Sartem if (dbus_message_get_type(m) != DBUS_MESSAGE_TYPE_METHOD_RETURN) 43718c2aff7Sartem goto malformed; 43818c2aff7Sartem 43918c2aff7Sartem if (!dbus_message_iter_init(m, &iter) || 44018c2aff7Sartem dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32) 44118c2aff7Sartem goto malformed; 44218c2aff7Sartem dbus_message_iter_get_basic(&iter, &exitt); 44318c2aff7Sartem 44418c2aff7Sartem if (!dbus_message_iter_next(&iter) || 44518c2aff7Sartem dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INT32) 44618c2aff7Sartem goto malformed; 44718c2aff7Sartem dbus_message_iter_get_basic(&iter, &return_code); 44818c2aff7Sartem 44918c2aff7Sartem while (dbus_message_iter_next(&iter) && 45018c2aff7Sartem dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING) { 45118c2aff7Sartem const char *value; 45218c2aff7Sartem dbus_message_iter_get_basic(&iter, &value); 45318c2aff7Sartem g_array_append_vals(error, &value, 1); 45418c2aff7Sartem } 45518c2aff7Sartem 45618c2aff7Sartem hb->cb(hb->d, exitt, return_code, 45718c2aff7Sartem (gchar **)error->data, hb->data1, hb->data2); 45818c2aff7Sartem 45918c2aff7Sartem g_object_unref (hb->d); 46018c2aff7Sartem 46118c2aff7Sartem dbus_message_unref(m); 46218c2aff7Sartem dbus_pending_call_unref (pending); 46318c2aff7Sartem g_array_free(error, TRUE); 46418c2aff7Sartem 46518c2aff7Sartem return; 46618c2aff7Sartem malformed: 46718c2aff7Sartem /* Send a Fail callback on malformed messages */ 46818c2aff7Sartem HAL_ERROR (("Malformed or unexpected reply message")); 46918c2aff7Sartem hb->cb(hb->d, HALD_RUN_FAILED, return_code, NULL, hb->data1, hb->data2); 47018c2aff7Sartem 47118c2aff7Sartem g_object_unref (hb->d); 47218c2aff7Sartem 47318c2aff7Sartem dbus_message_unref(m); 47418c2aff7Sartem dbus_pending_call_unref (pending); 47518c2aff7Sartem g_array_free(error, TRUE); 47618c2aff7Sartem } 47718c2aff7Sartem 47818c2aff7Sartem /* Run a helper program using the commandline, with input as infomation on 47918c2aff7Sartem * stdin */ 48018c2aff7Sartem void 48118c2aff7Sartem hald_runner_run_method(HalDevice *device, 48218c2aff7Sartem const gchar *command_line, char **extra_env, 48318c2aff7Sartem gchar *input, gboolean error_on_stderr, 48418c2aff7Sartem guint32 timeout, 48518c2aff7Sartem HalRunTerminatedCB cb, 48618c2aff7Sartem gpointer data1, gpointer data2) { 48718c2aff7Sartem DBusMessage *msg; 48818c2aff7Sartem DBusMessageIter iter; 48918c2aff7Sartem DBusPendingCall *call; 49018c2aff7Sartem HelperData *hd = NULL; 49118c2aff7Sartem msg = dbus_message_new_method_call("org.freedesktop.HalRunner", 49218c2aff7Sartem "/org/freedesktop/HalRunner", 49318c2aff7Sartem "org.freedesktop.HalRunner", 49418c2aff7Sartem "Run"); 49518c2aff7Sartem if (msg == NULL) 49618c2aff7Sartem DIE(("No memory")); 49718c2aff7Sartem dbus_message_iter_init_append(msg, &iter); 49818c2aff7Sartem 49918c2aff7Sartem if (!add_first_part(&iter, device, command_line, extra_env)) 50018c2aff7Sartem goto error; 50118c2aff7Sartem 50218c2aff7Sartem dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &input); 50318c2aff7Sartem dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &error_on_stderr); 50418c2aff7Sartem dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT32, &timeout); 50518c2aff7Sartem 50618c2aff7Sartem if (!dbus_connection_send_with_reply(runner_connection, 50718c2aff7Sartem msg, &call, INT_MAX)) 50818c2aff7Sartem DIE (("No memory")); 50918c2aff7Sartem 51061155e87SXiaolin Zhang - Sun Microsystems - Beijing China /* the connection was disconnected */ 51161155e87SXiaolin Zhang - Sun Microsystems - Beijing China if (call == NULL) 51261155e87SXiaolin Zhang - Sun Microsystems - Beijing China goto error; 51361155e87SXiaolin Zhang - Sun Microsystems - Beijing China 51418c2aff7Sartem hd = malloc(sizeof(HelperData)); 51518c2aff7Sartem hd->d = device; 51618c2aff7Sartem hd->cb = cb; 51718c2aff7Sartem hd->data1 = data1; 51818c2aff7Sartem hd->data2 = data2; 51918c2aff7Sartem 52018c2aff7Sartem g_object_ref (device); 52118c2aff7Sartem 52218c2aff7Sartem dbus_pending_call_set_notify(call, call_notify, hd, free); 52318c2aff7Sartem dbus_message_unref(msg); 52418c2aff7Sartem return; 52518c2aff7Sartem error: 52618c2aff7Sartem dbus_message_unref(msg); 52718c2aff7Sartem free(hd); 52818c2aff7Sartem cb(device, HALD_RUN_FAILED, 0, NULL, data1, data2); 52918c2aff7Sartem } 53018c2aff7Sartem 53118c2aff7Sartem void 53218c2aff7Sartem hald_runner_run(HalDevice *device, 53318c2aff7Sartem const gchar *command_line, char **extra_env, 53418c2aff7Sartem guint timeout, 53518c2aff7Sartem HalRunTerminatedCB cb, 53618c2aff7Sartem gpointer data1, gpointer data2) { 53718c2aff7Sartem hald_runner_run_method(device, command_line, extra_env, 53818c2aff7Sartem "", FALSE, timeout, cb, data1, data2); 53918c2aff7Sartem } 54018c2aff7Sartem 54118c2aff7Sartem 54218c2aff7Sartem 54318c2aff7Sartem void 54418c2aff7Sartem hald_runner_kill_device(HalDevice *device) { 54518c2aff7Sartem DBusMessage *msg, *reply; 54618c2aff7Sartem DBusError err; 54718c2aff7Sartem DBusMessageIter iter; 54818c2aff7Sartem const char *udi; 54918c2aff7Sartem 55018c2aff7Sartem running_processes_remove_device (device); 55118c2aff7Sartem 55218c2aff7Sartem msg = dbus_message_new_method_call("org.freedesktop.HalRunner", 55318c2aff7Sartem "/org/freedesktop/HalRunner", 55418c2aff7Sartem "org.freedesktop.HalRunner", 55518c2aff7Sartem "Kill"); 55618c2aff7Sartem if (msg == NULL) 55718c2aff7Sartem DIE(("No memory")); 55818c2aff7Sartem dbus_message_iter_init_append(msg, &iter); 55918c2aff7Sartem udi = hal_device_get_udi(device); 56018c2aff7Sartem dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &udi); 56118c2aff7Sartem 56218c2aff7Sartem /* Wait for the reply, should be almost instantanious */ 56318c2aff7Sartem dbus_error_init(&err); 56418c2aff7Sartem reply = 56518c2aff7Sartem dbus_connection_send_with_reply_and_block(runner_connection, msg, -1, &err); 56618c2aff7Sartem if (reply) { 56718c2aff7Sartem dbus_message_unref(reply); 56818c2aff7Sartem } 56918c2aff7Sartem 57018c2aff7Sartem dbus_message_unref(msg); 57118c2aff7Sartem } 57218c2aff7Sartem 57318c2aff7Sartem void 57418c2aff7Sartem hald_runner_kill_all(HalDevice *device) { 57518c2aff7Sartem DBusMessage *msg, *reply; 57618c2aff7Sartem DBusError err; 577*18c4e255SLin Guo - Sun Microsystems 578*18c4e255SLin Guo - Sun Microsystems /* hald_runner has not yet started, just return */ 579*18c4e255SLin Guo - Sun Microsystems if (runner_connection == NULL) { 580*18c4e255SLin Guo - Sun Microsystems return; 581*18c4e255SLin Guo - Sun Microsystems } 58218c2aff7Sartem 58318c2aff7Sartem running_processes_remove_device (device); 58418c2aff7Sartem 58518c2aff7Sartem msg = dbus_message_new_method_call("org.freedesktop.HalRunner", 58618c2aff7Sartem "/org/freedesktop/HalRunner", 58718c2aff7Sartem "org.freedesktop.HalRunner", 58818c2aff7Sartem "KillAll"); 58918c2aff7Sartem if (msg == NULL) 59018c2aff7Sartem DIE(("No memory")); 59118c2aff7Sartem 59218c2aff7Sartem /* Wait for the reply, should be almost instantanious */ 59318c2aff7Sartem dbus_error_init(&err); 59418c2aff7Sartem reply = 59518c2aff7Sartem dbus_connection_send_with_reply_and_block(runner_connection, 59618c2aff7Sartem msg, -1, &err); 59718c2aff7Sartem if (reply) { 59818c2aff7Sartem dbus_message_unref(reply); 59918c2aff7Sartem } 60018c2aff7Sartem 60118c2aff7Sartem dbus_message_unref(msg); 60218c2aff7Sartem } 603