18c2aff776a775d34a4c9893a4c72e0434d68e36artem/***************************************************************************
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * CVSID: $Id$
18c2aff776a775d34a4c9893a4c72e0434d68e36artem *
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * runner.c - Process running code
18c2aff776a775d34a4c9893a4c72e0434d68e36artem *
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * Copyright (C) 2006 Sjoerd Simons, <sjoerd@luon.net>
3ab06c272dba4a37b5b352788c61484729197623Milan Jurik * Copyright (C) 2007 Codethink Ltd. Author Rob Taylor <rob.taylor@codethink.co.uk>
18c2aff776a775d34a4c9893a4c72e0434d68e36artem *
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * Licensed under the Academic Free License version 2.1
18c2aff776a775d34a4c9893a4c72e0434d68e36artem *
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * This program is free software; you can redistribute it and/or modify
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * it under the terms of the GNU General Public License as published by
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * the Free Software Foundation; either version 2 of the License, or
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * (at your option) any later version.
18c2aff776a775d34a4c9893a4c72e0434d68e36artem *
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * This program is distributed in the hope that it will be useful,
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * but WITHOUT ANY WARRANTY; without even the implied warranty of
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * GNU General Public License for more details.
18c2aff776a775d34a4c9893a4c72e0434d68e36artem *
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * You should have received a copy of the GNU General Public License
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * along with this program; if not, write to the Free Software
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18c2aff776a775d34a4c9893a4c72e0434d68e36artem *
18c2aff776a775d34a4c9893a4c72e0434d68e36artem **************************************************************************/
18c2aff776a775d34a4c9893a4c72e0434d68e36artem#include <stdio.h>
18c2aff776a775d34a4c9893a4c72e0434d68e36artem#include <unistd.h>
18c2aff776a775d34a4c9893a4c72e0434d68e36artem#include <stdlib.h>
18c2aff776a775d34a4c9893a4c72e0434d68e36artem#include <sys/types.h>
18c2aff776a775d34a4c9893a4c72e0434d68e36artem#include <sys/stat.h>
18c2aff776a775d34a4c9893a4c72e0434d68e36artem#include <sys/wait.h>
18c2aff776a775d34a4c9893a4c72e0434d68e36artem#include <signal.h>
18c2aff776a775d34a4c9893a4c72e0434d68e36artem#include <string.h>
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem#define DBUS_API_SUBJECT_TO_CHANGE
18c2aff776a775d34a4c9893a4c72e0434d68e36artem#include <dbus/dbus-glib-lowlevel.h>
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem#include <glib.h>
18c2aff776a775d34a4c9893a4c72e0434d68e36artem#include "utils.h"
18c2aff776a775d34a4c9893a4c72e0434d68e36artem#include "runner.h"
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem/* Successful run of the program */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem#define HALD_RUN_SUCCESS 0x0
18c2aff776a775d34a4c9893a4c72e0434d68e36artem/* Process was killed because of running too long */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem#define HALD_RUN_TIMEOUT 0x1
18c2aff776a775d34a4c9893a4c72e0434d68e36artem/* Failed to start for some reason */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem#define HALD_RUN_FAILED 0x2
18c2aff776a775d34a4c9893a4c72e0434d68e36artem/* Killed on purpose, e.g. hal_util_kill_device_helpers */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem#define HALD_RUN_KILLED 0x4
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artemGHashTable *udi_hash = NULL;
3ab06c272dba4a37b5b352788c61484729197623Milan JurikGList *singletons = NULL;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artemtypedef struct {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem run_request *r;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem DBusMessage *msg;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem DBusConnection *con;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem GPid pid;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem gint stderr_v;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem guint watch;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem guint timeout;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem gboolean sent_kill;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem gboolean emit_pid_exited;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem} run_data;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artemstatic void
18c2aff776a775d34a4c9893a4c72e0434d68e36artemdel_run_data(run_data *rd)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem{
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (rd == NULL)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem return;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem del_run_request(rd->r);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (rd->msg)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem dbus_message_unref(rd->msg);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem g_spawn_close_pid(rd->pid);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (rd->stderr_v >= 0)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem close(rd->stderr_v);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (rd->timeout != 0)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem g_source_remove(rd->timeout);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem g_free(rd);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem}
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artemrun_request *
18c2aff776a775d34a4c9893a4c72e0434d68e36artemnew_run_request(void)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem{
18c2aff776a775d34a4c9893a4c72e0434d68e36artem run_request *result;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem result = g_new0(run_request, 1);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem g_assert(result != NULL);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem return result;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem}
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artemvoid
18c2aff776a775d34a4c9893a4c72e0434d68e36artemdel_run_request(run_request *r)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem{
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (r == NULL)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem return;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem g_free(r->udi);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem free_string_array(r->environment);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem free_string_array(r->argv);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem g_free(r->input);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem g_free(r);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem}
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artemstatic void
18c2aff776a775d34a4c9893a4c72e0434d68e36artemsend_reply(DBusConnection *con, DBusMessage *msg, guint32 exit_type, gint32 return_code, gchar **error)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem{
18c2aff776a775d34a4c9893a4c72e0434d68e36artem DBusMessage *reply;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem DBusMessageIter iter;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem int i;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (con == NULL || msg == NULL)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem return;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem reply = dbus_message_new_method_return(msg);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem g_assert(reply != NULL);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem dbus_message_iter_init_append(reply, &iter);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT32, &exit_type);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &return_code);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (error != NULL) for (i = 0; error[i] != NULL; i++) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &error[i]);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem }
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem dbus_connection_send(con, reply, NULL);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem dbus_message_unref(reply);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem}
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artemstatic void
3ab06c272dba4a37b5b352788c61484729197623Milan Jurikremove_run_data(run_data *rd)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem{
18c2aff776a775d34a4c9893a4c72e0434d68e36artem GList *list;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
3ab06c272dba4a37b5b352788c61484729197623Milan Jurik if (rd->r->is_singleton) {
3ab06c272dba4a37b5b352788c61484729197623Milan Jurik singletons = g_list_remove(singletons, rd);
3ab06c272dba4a37b5b352788c61484729197623Milan Jurik } else {
3ab06c272dba4a37b5b352788c61484729197623Milan Jurik /* Remove to the hashtable */
3ab06c272dba4a37b5b352788c61484729197623Milan Jurik list = (GList *)g_hash_table_lookup(udi_hash, rd->r->udi);
3ab06c272dba4a37b5b352788c61484729197623Milan Jurik list = g_list_remove(list, rd);
3ab06c272dba4a37b5b352788c61484729197623Milan Jurik /* The hash table will take care to not leak the dupped string */
3ab06c272dba4a37b5b352788c61484729197623Milan Jurik g_hash_table_insert(udi_hash, g_strdup(rd->r->udi), list);
3ab06c272dba4a37b5b352788c61484729197623Milan Jurik }
18c2aff776a775d34a4c9893a4c72e0434d68e36artem}
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artemstatic void
18c2aff776a775d34a4c9893a4c72e0434d68e36artemrun_exited(GPid pid, gint status, gpointer data)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem{
18c2aff776a775d34a4c9893a4c72e0434d68e36artem run_data *rd = (run_data *)data;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem char **error = NULL;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
3ab06c272dba4a37b5b352788c61484729197623Milan Jurik printf("pid %d: rc=%d signaled=%d: %s\n",
3ab06c272dba4a37b5b352788c61484729197623Milan Jurik pid, WEXITSTATUS(status), WIFSIGNALED(status), rd->r->argv[0]);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem rd->watch = 0;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (rd->sent_kill == TRUE) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* We send it a kill, so ignore */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem del_run_data(rd);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem return;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem }
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* Check if it was a normal exit */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (!WIFEXITED(status)) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* No not normal termination ? crash ? */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem send_reply(rd->con, rd->msg, HALD_RUN_FAILED, 0, NULL);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem goto out;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem }
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* normal exit */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (rd->stderr_v >= 0) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* Need to read stderr */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem error = get_string_array_from_fd(rd->stderr_v);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem close(rd->stderr_v);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem rd->stderr_v = -1;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem }
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (rd->msg != NULL)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem send_reply(rd->con, rd->msg, HALD_RUN_SUCCESS, WEXITSTATUS(status), error);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem free_string_array(error);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artemout:
3ab06c272dba4a37b5b352788c61484729197623Milan Jurik remove_run_data (rd);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* emit a signal that this PID exited */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if(rd->con != NULL && rd->emit_pid_exited) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem DBusMessage *signal;
3ab06c272dba4a37b5b352788c61484729197623Milan Jurik gint64 ppid = rd->pid;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem signal = dbus_message_new_signal ("/org/freedesktop/HalRunner",
18c2aff776a775d34a4c9893a4c72e0434d68e36artem "org.freedesktop.HalRunner",
18c2aff776a775d34a4c9893a4c72e0434d68e36artem "StartedProcessExited");
18c2aff776a775d34a4c9893a4c72e0434d68e36artem dbus_message_append_args (signal,
3ab06c272dba4a37b5b352788c61484729197623Milan Jurik DBUS_TYPE_INT64, &(ppid),
18c2aff776a775d34a4c9893a4c72e0434d68e36artem DBUS_TYPE_INVALID);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem dbus_connection_send(rd->con, signal, NULL);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem }
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem del_run_data(rd);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem}
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artemstatic gboolean
18c2aff776a775d34a4c9893a4c72e0434d68e36artemrun_timedout(gpointer data) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem run_data *rd = (run_data *)data;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* Time is up, kill the process, send reply that it was killed!
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * Don't wait for exit, because it could hang in state D
18c2aff776a775d34a4c9893a4c72e0434d68e36artem */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem kill(rd->pid, SIGTERM);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* Ensure the timeout is not removed in the delete */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem rd->timeout = 0;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* So the exit watch will know it's killed in case it runs*/
18c2aff776a775d34a4c9893a4c72e0434d68e36artem rd->sent_kill = TRUE;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem send_reply(rd->con, rd->msg, HALD_RUN_TIMEOUT, 0, NULL);
3ab06c272dba4a37b5b352788c61484729197623Milan Jurik remove_run_data (rd);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem return FALSE;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem}
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artemstatic gboolean
18c2aff776a775d34a4c9893a4c72e0434d68e36artemfind_program(char **argv)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem{
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* Search for the program in the dirs where it's allowed to be */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem char *program;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem char *path = NULL;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (argv[0] == NULL)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem return FALSE;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem program = g_path_get_basename(argv[0]);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* first search $PATH to make e.g. run-hald.sh work */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem path = g_find_program_in_path (program);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem g_free(program);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (path == NULL)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem return FALSE;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem else {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* Replace program in argv[0] with the full path */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem g_free(argv[0]);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem argv[0] = path;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem }
18c2aff776a775d34a4c9893a4c72e0434d68e36artem return TRUE;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem}
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem/* Run the given request and reply it's result on msg */
18c2aff776a775d34a4c9893a4c72e0434d68e36artemgboolean
18c2aff776a775d34a4c9893a4c72e0434d68e36artemrun_request_run (run_request *r, DBusConnection *con, DBusMessage *msg, GPid *out_pid)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem{
18c2aff776a775d34a4c9893a4c72e0434d68e36artem GPid pid;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem GError *error = NULL;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem gint *stdin_p = NULL;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem gint *stderr_p = NULL;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem gint stdin_v;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem gint stderr_v = -1;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem run_data *rd = NULL;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem gboolean program_exists = FALSE;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem char *program_dir = NULL;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem GList *list;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
3ab06c272dba4a37b5b352788c61484729197623Milan Jurik printf("Run started %s (%u) (%d) \n!", r->argv[0], r->timeout,
18c2aff776a775d34a4c9893a4c72e0434d68e36artem r->error_on_stderr);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (r->input != NULL) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem stdin_p = &stdin_v;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem }
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (r->error_on_stderr) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem stderr_p = &stderr_v;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem }
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem program_exists = find_program(r->argv);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
7544909da5f7d5b467625910225a72e142c4b6b7artem if (program_exists) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem program_dir = g_path_get_dirname (r->argv[0]);
7544909da5f7d5b467625910225a72e142c4b6b7artem printf(" full path is '%s', program_dir is '%s'\n", r->argv[0], program_dir);
7544909da5f7d5b467625910225a72e142c4b6b7artem }
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (!program_exists ||
18c2aff776a775d34a4c9893a4c72e0434d68e36artem !g_spawn_async_with_pipes(program_dir, r->argv, r->environment,
18c2aff776a775d34a4c9893a4c72e0434d68e36artem G_SPAWN_DO_NOT_REAP_CHILD,
18c2aff776a775d34a4c9893a4c72e0434d68e36artem NULL, NULL, &pid,
18c2aff776a775d34a4c9893a4c72e0434d68e36artem stdin_p, NULL, stderr_p, &error)) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem g_free (program_dir);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem del_run_request(r);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (con && msg)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem send_reply(con, msg, HALD_RUN_FAILED, 0, NULL);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem return FALSE;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem }
18c2aff776a775d34a4c9893a4c72e0434d68e36artem g_free (program_dir);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (r->input) {
b941d3fc4e70b4411341c7aeb53517bbff5f2df4artem if (write(stdin_v, r->input, strlen(r->input)) != (ssize_t) strlen(r->input))
3ab06c272dba4a37b5b352788c61484729197623Milan Jurik printf("Warning: Error while writing r->input (%s) to stdin_v.\n", r->input);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem close(stdin_v);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem }
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem rd = g_new0(run_data,1);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem g_assert(rd != NULL);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem rd->r = r;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem rd->msg = msg;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (msg != NULL)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem dbus_message_ref(msg);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem rd->con = con;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem rd->pid = pid;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem rd->stderr_v = stderr_v;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem rd->sent_kill = FALSE;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* Add watch for exit of the program */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem rd->watch = g_child_watch_add(pid, run_exited, rd);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* Add timeout if needed */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (r->timeout > 0)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem rd->timeout = g_timeout_add(r->timeout, run_timedout, rd);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem else
18c2aff776a775d34a4c9893a4c72e0434d68e36artem rd->timeout = 0;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
3ab06c272dba4a37b5b352788c61484729197623Milan Jurik if (r->is_singleton) {
3ab06c272dba4a37b5b352788c61484729197623Milan Jurik singletons = g_list_prepend(singletons, rd);
3ab06c272dba4a37b5b352788c61484729197623Milan Jurik } else {
3ab06c272dba4a37b5b352788c61484729197623Milan Jurik /* Add to the hashtable */
3ab06c272dba4a37b5b352788c61484729197623Milan Jurik list = (GList *)g_hash_table_lookup(udi_hash, r->udi);
3ab06c272dba4a37b5b352788c61484729197623Milan Jurik list = g_list_prepend(list, rd);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
3ab06c272dba4a37b5b352788c61484729197623Milan Jurik /* The hash table will take care to not leak the dupped string */
3ab06c272dba4a37b5b352788c61484729197623Milan Jurik g_hash_table_insert(udi_hash, g_strdup(r->udi), list);
3ab06c272dba4a37b5b352788c61484729197623Milan Jurik }
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* send back PID if requested.. and only emit StartedProcessExited in this case */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (out_pid != NULL) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem *out_pid = pid;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem rd->emit_pid_exited = TRUE;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem }
18c2aff776a775d34a4c9893a4c72e0434d68e36artem return TRUE;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem}
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artemstatic void
18c2aff776a775d34a4c9893a4c72e0434d68e36artemkill_rd(gpointer data, gpointer user_data)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem{
18c2aff776a775d34a4c9893a4c72e0434d68e36artem run_data *rd = (run_data *)data;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem kill(rd->pid, SIGTERM);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem printf("Sent kill to %d\n", rd->pid);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (rd->timeout != 0) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* Remove the timeout watch */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem g_source_remove(rd->timeout);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem rd->timeout = 0;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem }
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* So the exit watch will know it's killed in case it runs */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem rd->sent_kill = TRUE;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (rd->msg != NULL)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem send_reply(rd->con, rd->msg, HALD_RUN_KILLED, 0, NULL);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem}
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artemstatic void
18c2aff776a775d34a4c9893a4c72e0434d68e36artemdo_kill_udi(gchar *udi)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem{
18c2aff776a775d34a4c9893a4c72e0434d68e36artem GList *list;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem list = (GList *)g_hash_table_lookup(udi_hash, udi);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem g_list_foreach(list, kill_rd, NULL);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem g_list_free(list);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem}
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem/* Kill all running request for a udi */
18c2aff776a775d34a4c9893a4c72e0434d68e36artemvoid
18c2aff776a775d34a4c9893a4c72e0434d68e36artemrun_kill_udi(gchar *udi)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem{
18c2aff776a775d34a4c9893a4c72e0434d68e36artem do_kill_udi(udi);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem g_hash_table_remove(udi_hash, udi);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem}
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artemstatic gboolean
18c2aff776a775d34a4c9893a4c72e0434d68e36artemhash_kill_udi(gpointer key, gpointer value, gpointer user_data) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem do_kill_udi(key);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem return TRUE;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem}
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem/* Kill all running request*/
18c2aff776a775d34a4c9893a4c72e0434d68e36artemvoid
18c2aff776a775d34a4c9893a4c72e0434d68e36artemrun_kill_all()
18c2aff776a775d34a4c9893a4c72e0434d68e36artem{
18c2aff776a775d34a4c9893a4c72e0434d68e36artem g_hash_table_foreach_remove(udi_hash, hash_kill_udi, NULL);
3ab06c272dba4a37b5b352788c61484729197623Milan Jurik g_list_foreach(singletons, kill_rd, NULL);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem}
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artemvoid
18c2aff776a775d34a4c9893a4c72e0434d68e36artemrun_init()
18c2aff776a775d34a4c9893a4c72e0434d68e36artem{
18c2aff776a775d34a4c9893a4c72e0434d68e36artem udi_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem}