xref: /titanic_52/usr/src/cmd/hal/hald/hald_runner.c (revision 18c4e255539c8eac2a18c73be8729ec1f6fa818a)
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