xref: /onnv-gate/usr/src/cmd/hal/hald/hald_runner.c (revision 12395:50bdcae3feb5)
12912Sartem /***************************************************************************
22912Sartem  * CVSID: $Id$
32912Sartem  *
42912Sartem  * hald_runner.c - Interface to the hal runner helper daemon
52912Sartem  *
62912Sartem  * Copyright (C) 2006 Sjoerd Simons, <sjoerd@luon.net>
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 <sys/utsname.h>
312912Sartem #include <stdio.h>
322912Sartem 
332912Sartem #include <glib.h>
342912Sartem #include <dbus/dbus.h>
352912Sartem #include <dbus/dbus-glib-lowlevel.h>
362912Sartem 
372912Sartem #include "hald.h"
382912Sartem #include "util.h"
392912Sartem #include "logger.h"
402912Sartem #include "hald_dbus.h"
412912Sartem #include "hald_runner.h"
422912Sartem 
432912Sartem typedef struct {
442912Sartem   HalDevice *d;
452912Sartem   HalRunTerminatedCB cb;
462912Sartem   gpointer data1;
472912Sartem   gpointer data2;
482912Sartem } HelperData;
492912Sartem 
502912Sartem #define DBUS_SERVER_ADDRESS "unix:tmpdir=" HALD_SOCKET_DIR
512912Sartem 
522912Sartem static DBusConnection *runner_connection = NULL;
532912Sartem 
542912Sartem typedef struct
552912Sartem {
562912Sartem 	GPid pid;
572912Sartem 	HalDevice *device;
582912Sartem 	HalRunTerminatedCB cb;
592912Sartem 	gpointer data1;
602912Sartem 	gpointer data2;
612912Sartem } RunningProcess;
622912Sartem 
632912Sartem /* mapping from PID to RunningProcess */
642912Sartem static GHashTable *running_processes;
652912Sartem 
662912Sartem static gboolean
rprd_foreach(gpointer key,gpointer value,gpointer user_data)672912Sartem rprd_foreach (gpointer key,
682912Sartem 	      gpointer value,
692912Sartem 	      gpointer user_data)
702912Sartem {
712912Sartem 	gboolean remove = FALSE;
722912Sartem 	RunningProcess *rp = value;
732912Sartem 	HalDevice *device = user_data;
742912Sartem 
752912Sartem 	if (rp->device == device) {
762912Sartem 		remove = TRUE;
772912Sartem 		g_free (rp);
782912Sartem 	}
792912Sartem 
802912Sartem 	return remove;
812912Sartem }
822912Sartem 
832912Sartem static void
running_processes_remove_device(HalDevice * device)842912Sartem running_processes_remove_device (HalDevice *device)
852912Sartem {
862912Sartem 	g_hash_table_foreach_remove (running_processes, rprd_foreach, device);
872912Sartem }
882912Sartem 
892912Sartem void
runner_device_finalized(HalDevice * device)902912Sartem runner_device_finalized (HalDevice *device)
912912Sartem {
922912Sartem 	running_processes_remove_device (device);
932912Sartem }
942912Sartem 
952912Sartem 
962912Sartem static DBusHandlerResult
runner_server_message_handler(DBusConnection * connection,DBusMessage * message,void * user_data)972912Sartem runner_server_message_handler (DBusConnection *connection,
982912Sartem 			       DBusMessage *message,
992912Sartem 			       void *user_data)
1002912Sartem {
1012912Sartem 
1022912Sartem 	/*HAL_INFO (("runner_server_message_handler: destination=%s obj_path=%s interface=%s method=%s",
1032912Sartem 		   dbus_message_get_destination (message),
1042912Sartem 		   dbus_message_get_path (message),
1052912Sartem 		   dbus_message_get_interface (message),
1062912Sartem 		   dbus_message_get_member (message)));*/
1072912Sartem 	if (dbus_message_is_signal (message,
1082912Sartem 				    "org.freedesktop.HalRunner",
1092912Sartem 				    "StartedProcessExited")) {
1102912Sartem 		dbus_uint64_t dpid;
1112912Sartem 		DBusError error;
1122912Sartem 		dbus_error_init (&error);
1132912Sartem 		if (dbus_message_get_args (message, &error,
1142912Sartem 					   DBUS_TYPE_INT64, &dpid,
1152912Sartem 					   DBUS_TYPE_INVALID)) {
1162912Sartem 			RunningProcess *rp;
1172912Sartem 			GPid pid;
1182912Sartem 
1192912Sartem 			pid = (GPid) dpid;
1202912Sartem 
1212912Sartem 			/*HAL_INFO (("Previously started process with pid %d exited", pid));*/
1222912Sartem 			rp = g_hash_table_lookup (running_processes, (gpointer) pid);
1232912Sartem 			if (rp != NULL) {
1242912Sartem 				rp->cb (rp->device, 0, 0, NULL, rp->data1, rp->data2);
1252912Sartem 				g_hash_table_remove (running_processes, (gpointer) pid);
1262912Sartem 				g_free (rp);
1272912Sartem 			}
1282912Sartem 		}
1292912Sartem 	}
1302912Sartem 	return DBUS_HANDLER_RESULT_HANDLED;
1312912Sartem }
1322912Sartem 
1332912Sartem static void
runner_server_unregister_handler(DBusConnection * connection,void * user_data)1342912Sartem runner_server_unregister_handler (DBusConnection *connection, void *user_data)
1352912Sartem {
1362912Sartem 	HAL_INFO (("unregistered"));
1372912Sartem }
1382912Sartem 
1392912Sartem 
1402912Sartem static void
handle_connection(DBusServer * server,DBusConnection * new_connection,void * data)1412912Sartem handle_connection(DBusServer *server,
1422912Sartem                   DBusConnection *new_connection,
1432912Sartem                   void *data)
1442912Sartem {
1452912Sartem 
1462912Sartem 	if (runner_connection == NULL) {
1472912Sartem 		DBusObjectPathVTable vtable = { &runner_server_unregister_handler,
1482912Sartem 						&runner_server_message_handler,
1492912Sartem 						NULL, NULL, NULL, NULL};
1502912Sartem 
1512912Sartem 		runner_connection = new_connection;
1522912Sartem 		dbus_connection_ref (new_connection);
1532912Sartem 		dbus_connection_setup_with_g_main (new_connection, NULL);
1542912Sartem 
1552912Sartem 		dbus_connection_register_fallback (new_connection,
1562912Sartem 						   "/org/freedesktop",
1572912Sartem 						   &vtable,
1582912Sartem 						   NULL);
1592912Sartem 
1602912Sartem 		/* dbus_server_unref(server); */
1612912Sartem 
1622912Sartem 	}
1632912Sartem }
1642912Sartem 
1652912Sartem static void
runner_died(GPid pid,gint status,gpointer data)1662912Sartem runner_died(GPid pid, gint status, gpointer data) {
1672912Sartem   g_spawn_close_pid (pid);
1682912Sartem   DIE (("Runner died"));
1692912Sartem }
1702912Sartem 
1712912Sartem gboolean
hald_runner_start_runner(void)1722912Sartem hald_runner_start_runner(void)
1732912Sartem {
1742912Sartem   DBusServer *server = NULL;
1752912Sartem   DBusError err;
1762912Sartem   GError *error = NULL;
1772912Sartem   GPid pid;
1782912Sartem   char *argv[] = { NULL, NULL};
1792912Sartem   char *env[] =  { NULL, NULL, NULL, NULL};
1802912Sartem   const char *hald_runner_path;
1812912Sartem   char *server_addr;
1822912Sartem 
1832912Sartem   running_processes = g_hash_table_new (g_direct_hash, g_direct_equal);
1842912Sartem 
1852912Sartem   dbus_error_init(&err);
1862912Sartem   server = dbus_server_listen(DBUS_SERVER_ADDRESS, &err);
1872912Sartem   if (server == NULL) {
1882912Sartem     HAL_ERROR (("Cannot create D-BUS server for the runner"));
1892912Sartem     goto error;
1902912Sartem   }
1912912Sartem 
1922912Sartem   dbus_server_setup_with_g_main(server, NULL);
1932912Sartem   dbus_server_set_new_connection_function(server, handle_connection,
1942912Sartem                                           NULL, NULL);
1952912Sartem 
1962912Sartem 
1972912Sartem   argv[0] = "hald-runner";
1982912Sartem   server_addr = dbus_server_get_address (server);
1992912Sartem   env[0] = g_strdup_printf("HALD_RUNNER_DBUS_ADDRESS=%s", server_addr);
2002912Sartem   dbus_free (server_addr);
2012912Sartem   hald_runner_path = g_getenv("HALD_RUNNER_PATH");
2022912Sartem   if (hald_runner_path != NULL) {
2032912Sartem 	  env[1] = g_strdup_printf ("PATH=%s:" PACKAGE_LIBEXEC_DIR ":" PACKAGE_SCRIPT_DIR ":" PACKAGE_BIN_DIR, hald_runner_path);
2042912Sartem   } else {
2052912Sartem 	  env[1] = g_strdup_printf ("PATH=" PACKAGE_LIBEXEC_DIR ":" PACKAGE_SCRIPT_DIR ":" PACKAGE_BIN_DIR);
2062912Sartem   }
2072912Sartem 
2082912Sartem   /*env[2] = "DBUS_VERBOSE=1";*/
2092912Sartem 
2102912Sartem 
2112912Sartem   if (!g_spawn_async(NULL, argv, env, G_SPAWN_DO_NOT_REAP_CHILD|G_SPAWN_SEARCH_PATH,
2122912Sartem         NULL, NULL, &pid, &error)) {
2132912Sartem     HAL_ERROR (("Could not spawn runner : '%s'", error->message));
2142912Sartem     g_error_free (error);
2152912Sartem     goto error;
2162912Sartem   }
2172912Sartem   g_free(env[0]);
2182912Sartem   g_free(env[1]);
2192912Sartem 
2202912Sartem   HAL_INFO (("Runner has pid %d", pid));
2212912Sartem 
2222912Sartem   g_child_watch_add(pid, runner_died, NULL);
2232912Sartem   while (runner_connection == NULL) {
2242912Sartem     /* Wait for the runner */
2252912Sartem     g_main_context_iteration(NULL, TRUE);
2262912Sartem   }
2272912Sartem   return TRUE;
2282912Sartem 
2292912Sartem error:
2302912Sartem   if (server != NULL)
2312912Sartem     dbus_server_unref(server);
2322912Sartem   return FALSE;
2332912Sartem }
2342912Sartem 
2352912Sartem static gboolean
add_property_to_msg(HalDevice * device,HalProperty * property,gpointer user_data)2362912Sartem add_property_to_msg (HalDevice *device, HalProperty *property,
2372912Sartem                                      gpointer user_data)
2382912Sartem {
2392912Sartem   char *prop_upper, *value;
2402912Sartem   char *c;
2412912Sartem   gchar *env;
2422912Sartem   DBusMessageIter *iter = (DBusMessageIter *)user_data;
2432912Sartem 
2442912Sartem   prop_upper = g_ascii_strup (hal_property_get_key (property), -1);
2452912Sartem 
2462912Sartem   /* periods aren't valid in the environment, so replace them with
2472912Sartem    * underscores. */
2482912Sartem   for (c = prop_upper; *c; c++) {
2492912Sartem     if (*c == '.')
2502912Sartem       *c = '_';
2512912Sartem   }
2522912Sartem 
2532912Sartem   value = hal_property_to_string (property);
2542912Sartem   env = g_strdup_printf ("HAL_PROP_%s=%s", prop_upper, value);
2552912Sartem   dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &env);
2562912Sartem 
2572912Sartem   g_free (env);
2582912Sartem   g_free (value);
2592912Sartem   g_free (prop_upper);
2602912Sartem 
2612912Sartem   return TRUE;
2622912Sartem }
2632912Sartem 
2642912Sartem static void
add_env(DBusMessageIter * iter,const gchar * key,const gchar * value)2652912Sartem add_env(DBusMessageIter *iter, const gchar *key, const gchar *value) {
2662912Sartem   gchar *env;
2672912Sartem   env = g_strdup_printf ("%s=%s", key, value);
2682912Sartem   dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &env);
2692912Sartem   g_free(env);
2702912Sartem }
2712912Sartem 
2722912Sartem static void
add_basic_env(DBusMessageIter * iter,const gchar * udi)2732912Sartem add_basic_env(DBusMessageIter *iter, const gchar *udi) {
2742912Sartem   struct utsname un;
2752912Sartem   char *server_addr;
2762912Sartem 
2772912Sartem   if (hald_is_verbose) {
2782912Sartem     add_env(iter, "HALD_VERBOSE", "1");
2792912Sartem   }
2802912Sartem   if (hald_is_initialising) {
2812912Sartem     add_env(iter, "HALD_STARTUP", "1");
2822912Sartem   }
2832912Sartem   if (hald_use_syslog) {
2842912Sartem     add_env(iter, "HALD_USE_SYSLOG", "1");
2852912Sartem   }
2862912Sartem   add_env(iter, "UDI", udi);
2872912Sartem   server_addr = hald_dbus_local_server_addr();
2882912Sartem   add_env(iter, "HALD_DIRECT_ADDR", server_addr);
2892912Sartem   dbus_free (server_addr);
2902912Sartem #ifdef HAVE_POLKIT
2912912Sartem   add_env(iter, "HAVE_POLKIT", "1");
2922912Sartem #endif
2932912Sartem 
2946573Sphitran   if (uname(&un) >= 0) {
2952912Sartem     char *sysname;
2962912Sartem 
2972912Sartem     sysname = g_ascii_strdown(un.sysname, -1);
2982912Sartem     add_env(iter, "HALD_UNAME_S", sysname);
2992912Sartem     g_free(sysname);
3002912Sartem   }
3012912Sartem }
3022912Sartem 
3032912Sartem static void
add_extra_env(DBusMessageIter * iter,gchar ** env)3042912Sartem add_extra_env(DBusMessageIter *iter, gchar **env) {
3052912Sartem   int i;
3062912Sartem   if (env != NULL) for (i = 0; env[i] != NULL; i++) {
3072912Sartem     dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &env[i]);
3082912Sartem   }
3092912Sartem }
3102912Sartem 
3112912Sartem static gboolean
add_command(DBusMessageIter * iter,const gchar * command_line)3122912Sartem add_command(DBusMessageIter *iter, const gchar *command_line) {
3132912Sartem   gint argc;
3142912Sartem   gint x;
3152912Sartem   char **argv;
3162912Sartem   GError *err = NULL;
3172912Sartem   DBusMessageIter array_iter;
3182912Sartem 
3192912Sartem   if (!g_shell_parse_argv(command_line, &argc, &argv, &err)) {
3202912Sartem     HAL_ERROR (("Error parsing commandline '%s': %s",
3212912Sartem                  command_line, err->message));
3222912Sartem     g_error_free (err);
3232912Sartem     return FALSE;
3242912Sartem   }
3252912Sartem   if (!dbus_message_iter_open_container(iter,
3262912Sartem                                    DBUS_TYPE_ARRAY,
3272912Sartem                                    DBUS_TYPE_STRING_AS_STRING,
3282912Sartem                                    &array_iter))
3292912Sartem     DIE (("No memory"));
3302912Sartem   for (x = 0 ; argv[x] != NULL; x++) {
3312912Sartem     dbus_message_iter_append_basic(&array_iter, DBUS_TYPE_STRING, &argv[x]);
3322912Sartem   }
3332912Sartem   dbus_message_iter_close_container(iter, &array_iter);
3342912Sartem 
3352912Sartem   g_strfreev(argv);
3362912Sartem   return TRUE;
3372912Sartem }
3382912Sartem 
3392912Sartem static gboolean
add_first_part(DBusMessageIter * iter,HalDevice * device,const gchar * command_line,char ** extra_env)3402912Sartem add_first_part(DBusMessageIter *iter, HalDevice *device,
3412912Sartem                    const gchar *command_line, char **extra_env) {
3422912Sartem   DBusMessageIter array_iter;
3432912Sartem   const char *udi;
3442912Sartem 
3452912Sartem   udi = hal_device_get_udi(device);
3462912Sartem   dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &udi);
3472912Sartem 
3482912Sartem   dbus_message_iter_open_container(iter,
3492912Sartem                                    DBUS_TYPE_ARRAY,
3502912Sartem                                    DBUS_TYPE_STRING_AS_STRING,
3512912Sartem                                    &array_iter);
3522912Sartem   hal_device_property_foreach (device, add_property_to_msg, &array_iter);
3532912Sartem   add_basic_env(&array_iter, udi);
3542912Sartem   add_extra_env(&array_iter, extra_env);
3552912Sartem   dbus_message_iter_close_container(iter, &array_iter);
3562912Sartem 
3572912Sartem   if (!add_command(iter, command_line)) {
3582912Sartem     return FALSE;
3592912Sartem   }
3602912Sartem   return TRUE;
3612912Sartem }
3622912Sartem 
3632912Sartem /* Start a helper, returns true on a successfull start */
3642912Sartem gboolean
hald_runner_start(HalDevice * device,const gchar * command_line,char ** extra_env,HalRunTerminatedCB cb,gpointer data1,gpointer data2)3652912Sartem hald_runner_start (HalDevice *device, const gchar *command_line, char **extra_env,
3662912Sartem 		   HalRunTerminatedCB cb, gpointer data1, gpointer data2)
3672912Sartem {
3682912Sartem   DBusMessage *msg, *reply;
3692912Sartem   DBusError err;
3702912Sartem   DBusMessageIter iter;
3712912Sartem 
3722912Sartem   dbus_error_init(&err);
3732912Sartem   msg = dbus_message_new_method_call("org.freedesktop.HalRunner",
3742912Sartem                                      "/org/freedesktop/HalRunner",
3752912Sartem                                      "org.freedesktop.HalRunner",
3762912Sartem                                      "Start");
3772912Sartem   if (msg == NULL)
3782912Sartem     DIE(("No memory"));
3792912Sartem   dbus_message_iter_init_append(msg, &iter);
3802912Sartem 
3812912Sartem   if (!add_first_part(&iter, device, command_line, extra_env))
3822912Sartem     goto error;
3832912Sartem 
3842912Sartem   /* Wait for the reply, should be almost instantanious */
3852912Sartem   reply =
3862912Sartem     dbus_connection_send_with_reply_and_block(runner_connection,
3872912Sartem                                               msg, -1, &err);
3882912Sartem   if (reply) {
3892912Sartem     gboolean ret =
3902912Sartem       (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_METHOD_RETURN);
3912912Sartem 
3922912Sartem     if (ret) {
3932912Sartem 	dbus_int64_t pid_from_runner;
3942912Sartem 	if (dbus_message_get_args (reply, &err,
3952912Sartem 				   DBUS_TYPE_INT64, &pid_from_runner,
3962912Sartem 				   DBUS_TYPE_INVALID)) {
3972912Sartem 		if (cb != NULL) {
3982912Sartem 			RunningProcess *rp;
3992912Sartem 			rp = g_new0 (RunningProcess, 1);
4002912Sartem 			rp->pid = (GPid) pid_from_runner;
4012912Sartem 			rp->cb = cb;
4022912Sartem 			rp->device = device;
4032912Sartem 			rp->data1 = data1;
4042912Sartem 			rp->data2 = data2;
4052912Sartem 
4062912Sartem 			g_hash_table_insert (running_processes, (gpointer) rp->pid, rp);
4072912Sartem 		}
4082912Sartem 	} else {
4092912Sartem 	  HAL_ERROR (("Error extracting out_pid from runner's Start()"));
4102912Sartem 	}
4112912Sartem     }
4122912Sartem 
4132912Sartem     dbus_message_unref(reply);
4142912Sartem     dbus_message_unref(msg);
4152912Sartem     return ret;
4162912Sartem   }
4172912Sartem 
4182912Sartem error:
4192912Sartem   dbus_message_unref(msg);
4202912Sartem   return FALSE;
4212912Sartem }
4222912Sartem 
4232912Sartem static void
call_notify(DBusPendingCall * pending,void * user_data)4242912Sartem call_notify(DBusPendingCall *pending, void *user_data)
4252912Sartem {
4262912Sartem   HelperData *hb = (HelperData *)user_data;
4272912Sartem   dbus_uint32_t exitt = HALD_RUN_SUCCESS;
4282912Sartem   dbus_int32_t return_code = 0;
4292912Sartem   DBusMessage *m;
4302912Sartem   GArray *error = NULL;
4312912Sartem   DBusMessageIter iter;
4322912Sartem 
4332912Sartem   error = g_array_new(TRUE, FALSE, sizeof(char *));
4342912Sartem 
4352912Sartem   m = dbus_pending_call_steal_reply(pending);
4362912Sartem   if (dbus_message_get_type(m) != DBUS_MESSAGE_TYPE_METHOD_RETURN)
4372912Sartem     goto malformed;
4382912Sartem 
4392912Sartem   if (!dbus_message_iter_init(m, &iter) ||
4402912Sartem        dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
4412912Sartem     goto malformed;
4422912Sartem   dbus_message_iter_get_basic(&iter, &exitt);
4432912Sartem 
4442912Sartem   if (!dbus_message_iter_next(&iter) ||
4452912Sartem         dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INT32)
4462912Sartem     goto malformed;
4472912Sartem   dbus_message_iter_get_basic(&iter, &return_code);
4482912Sartem 
4492912Sartem   while (dbus_message_iter_next(&iter) &&
4502912Sartem     dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING) {
4512912Sartem     const char *value;
4522912Sartem     dbus_message_iter_get_basic(&iter, &value);
4532912Sartem     g_array_append_vals(error, &value, 1);
4542912Sartem   }
4552912Sartem 
4562912Sartem   hb->cb(hb->d, exitt, return_code,
4572912Sartem       (gchar **)error->data, hb->data1, hb->data2);
4582912Sartem 
4592912Sartem   g_object_unref (hb->d);
4602912Sartem 
4612912Sartem   dbus_message_unref(m);
4622912Sartem   dbus_pending_call_unref (pending);
4632912Sartem   g_array_free(error, TRUE);
4642912Sartem 
4652912Sartem   return;
4662912Sartem malformed:
4672912Sartem   /* Send a Fail callback on malformed messages */
4682912Sartem   HAL_ERROR (("Malformed or unexpected reply message"));
4692912Sartem   hb->cb(hb->d, HALD_RUN_FAILED, return_code, NULL, hb->data1, hb->data2);
4702912Sartem 
4712912Sartem   g_object_unref (hb->d);
4722912Sartem 
4732912Sartem   dbus_message_unref(m);
4742912Sartem   dbus_pending_call_unref (pending);
4752912Sartem   g_array_free(error, TRUE);
4762912Sartem }
4772912Sartem 
4782912Sartem /* Run a helper program using the commandline, with input as infomation on
4792912Sartem  * stdin */
4802912Sartem void
hald_runner_run_method(HalDevice * device,const gchar * command_line,char ** extra_env,gchar * input,gboolean error_on_stderr,guint32 timeout,HalRunTerminatedCB cb,gpointer data1,gpointer data2)4812912Sartem hald_runner_run_method(HalDevice *device,
4822912Sartem                            const gchar *command_line, char **extra_env,
4832912Sartem                            gchar *input, gboolean error_on_stderr,
4842912Sartem                            guint32 timeout,
4852912Sartem                            HalRunTerminatedCB  cb,
4862912Sartem                            gpointer data1, gpointer data2) {
4872912Sartem   DBusMessage *msg;
4882912Sartem   DBusMessageIter iter;
4892912Sartem   DBusPendingCall *call;
4902912Sartem   HelperData *hd = NULL;
4912912Sartem   msg = dbus_message_new_method_call("org.freedesktop.HalRunner",
4922912Sartem                              "/org/freedesktop/HalRunner",
4932912Sartem                              "org.freedesktop.HalRunner",
4942912Sartem                              "Run");
4952912Sartem   if (msg == NULL)
4962912Sartem     DIE(("No memory"));
4972912Sartem   dbus_message_iter_init_append(msg, &iter);
4982912Sartem 
4992912Sartem   if (!add_first_part(&iter, device, command_line, extra_env))
5002912Sartem     goto error;
5012912Sartem 
5022912Sartem   dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &input);
5032912Sartem   dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &error_on_stderr);
5042912Sartem   dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT32, &timeout);
5052912Sartem 
5062912Sartem   if (!dbus_connection_send_with_reply(runner_connection,
5072912Sartem                                               msg, &call, INT_MAX))
5082912Sartem     DIE (("No memory"));
5092912Sartem 
51010658SXiao-Lin.Zhang@Sun.COM   /* the connection was disconnected */
51110658SXiao-Lin.Zhang@Sun.COM   if (call == NULL)
51210658SXiao-Lin.Zhang@Sun.COM     goto error;
51310658SXiao-Lin.Zhang@Sun.COM 
5142912Sartem   hd = malloc(sizeof(HelperData));
5152912Sartem   hd->d = device;
5162912Sartem   hd->cb = cb;
5172912Sartem   hd->data1 = data1;
5182912Sartem   hd->data2 = data2;
5192912Sartem 
5202912Sartem   g_object_ref (device);
5212912Sartem 
5222912Sartem   dbus_pending_call_set_notify(call, call_notify, hd, free);
5232912Sartem   dbus_message_unref(msg);
5242912Sartem   return;
5252912Sartem error:
5262912Sartem   dbus_message_unref(msg);
5272912Sartem   free(hd);
5282912Sartem   cb(device, HALD_RUN_FAILED, 0, NULL, data1, data2);
5292912Sartem }
5302912Sartem 
5312912Sartem void
hald_runner_run(HalDevice * device,const gchar * command_line,char ** extra_env,guint timeout,HalRunTerminatedCB cb,gpointer data1,gpointer data2)5322912Sartem hald_runner_run(HalDevice *device,
5332912Sartem                     const gchar *command_line, char **extra_env,
5342912Sartem                     guint timeout,
5352912Sartem                     HalRunTerminatedCB  cb,
5362912Sartem                     gpointer data1, gpointer data2) {
5372912Sartem   hald_runner_run_method(device, command_line, extra_env,
5382912Sartem                              "", FALSE, timeout, cb, data1, data2);
5392912Sartem }
5402912Sartem 
5412912Sartem 
5422912Sartem 
5432912Sartem void
hald_runner_kill_device(HalDevice * device)5442912Sartem hald_runner_kill_device(HalDevice *device) {
5452912Sartem   DBusMessage *msg, *reply;
5462912Sartem   DBusError err;
5472912Sartem   DBusMessageIter iter;
5482912Sartem   const char *udi;
5492912Sartem 
5502912Sartem   running_processes_remove_device (device);
5512912Sartem 
5522912Sartem   msg = dbus_message_new_method_call("org.freedesktop.HalRunner",
5532912Sartem                              "/org/freedesktop/HalRunner",
5542912Sartem                              "org.freedesktop.HalRunner",
5552912Sartem                              "Kill");
5562912Sartem   if (msg == NULL)
5572912Sartem     DIE(("No memory"));
5582912Sartem   dbus_message_iter_init_append(msg, &iter);
5592912Sartem   udi = hal_device_get_udi(device);
5602912Sartem   dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &udi);
5612912Sartem 
5622912Sartem   /* Wait for the reply, should be almost instantanious */
5632912Sartem   dbus_error_init(&err);
5642912Sartem   reply =
5652912Sartem     dbus_connection_send_with_reply_and_block(runner_connection, msg, -1, &err);
5662912Sartem   if (reply) {
5672912Sartem     dbus_message_unref(reply);
5682912Sartem   }
5692912Sartem 
5702912Sartem   dbus_message_unref(msg);
5712912Sartem }
5722912Sartem 
5732912Sartem void
hald_runner_kill_all(HalDevice * device)5742912Sartem hald_runner_kill_all(HalDevice *device) {
5752912Sartem   DBusMessage *msg, *reply;
5762912Sartem   DBusError err;
577*12395SLin.Guo@Sun.COM 
578*12395SLin.Guo@Sun.COM   /* hald_runner has not yet started, just return */
579*12395SLin.Guo@Sun.COM   if (runner_connection == NULL) {
580*12395SLin.Guo@Sun.COM     return;
581*12395SLin.Guo@Sun.COM   }
5822912Sartem 
5832912Sartem   running_processes_remove_device (device);
5842912Sartem 
5852912Sartem   msg = dbus_message_new_method_call("org.freedesktop.HalRunner",
5862912Sartem                              "/org/freedesktop/HalRunner",
5872912Sartem                              "org.freedesktop.HalRunner",
5882912Sartem                              "KillAll");
5892912Sartem   if (msg == NULL)
5902912Sartem     DIE(("No memory"));
5912912Sartem 
5922912Sartem   /* Wait for the reply, should be almost instantanious */
5932912Sartem   dbus_error_init(&err);
5942912Sartem   reply =
5952912Sartem     dbus_connection_send_with_reply_and_block(runner_connection,
5962912Sartem                                               msg, -1, &err);
5972912Sartem   if (reply) {
5982912Sartem     dbus_message_unref(reply);
5992912Sartem   }
6002912Sartem 
6012912Sartem   dbus_message_unref(msg);
6022912Sartem }
603