1*2912Sartem /*************************************************************************** 2*2912Sartem * CVSID: $Id$ 3*2912Sartem * 4*2912Sartem * main.c - Main dbus interface of the hald runner 5*2912Sartem * 6*2912Sartem * Copyright (C) 2006 Sjoerd Simons, <sjoerd@luon.net> 7*2912Sartem * 8*2912Sartem * Licensed under the Academic Free License version 2.1 9*2912Sartem * 10*2912Sartem * This program is free software; you can redistribute it and/or modify 11*2912Sartem * it under the terms of the GNU General Public License as published by 12*2912Sartem * the Free Software Foundation; either version 2 of the License, or 13*2912Sartem * (at your option) any later version. 14*2912Sartem * 15*2912Sartem * This program is distributed in the hope that it will be useful, 16*2912Sartem * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*2912Sartem * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*2912Sartem * GNU General Public License for more details. 19*2912Sartem * 20*2912Sartem * You should have received a copy of the GNU General Public License 21*2912Sartem * along with this program; if not, write to the Free Software 22*2912Sartem * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 23*2912Sartem * 24*2912Sartem **************************************************************************/ 25*2912Sartem #include <stdio.h> 26*2912Sartem #include <stdlib.h> 27*2912Sartem #define DBUS_API_SUBJECT_TO_CHANGE 28*2912Sartem #include <dbus/dbus-glib-lowlevel.h> 29*2912Sartem 30*2912Sartem #include <glib.h> 31*2912Sartem #include "utils.h" 32*2912Sartem #include "runner.h" 33*2912Sartem 34*2912Sartem static gboolean 35*2912Sartem parse_first_part(run_request *r, DBusMessage *msg, DBusMessageIter *iter) 36*2912Sartem { 37*2912Sartem DBusMessageIter sub_iter; 38*2912Sartem char *tmpstr; 39*2912Sartem 40*2912Sartem /* First should be the device UDI */ 41*2912Sartem if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING) 42*2912Sartem goto malformed; 43*2912Sartem dbus_message_iter_get_basic(iter, &tmpstr); 44*2912Sartem r->udi = g_strdup(tmpstr); 45*2912Sartem 46*2912Sartem /* Then the environment array */ 47*2912Sartem if (!dbus_message_iter_next(iter) || dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) 48*2912Sartem goto malformed; 49*2912Sartem dbus_message_iter_recurse(iter, &sub_iter); 50*2912Sartem /* Add default path for the programs we start */ 51*2912Sartem tmpstr = g_strdup_printf("PATH=/sbin:/usr/sbin:/bin:/usr/bin:%s", getenv("PATH")); 52*2912Sartem r->environment = get_string_array(&sub_iter, tmpstr); 53*2912Sartem 54*2912Sartem /* Then argv */ 55*2912Sartem if (!dbus_message_iter_next(iter) || dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) 56*2912Sartem goto malformed; 57*2912Sartem dbus_message_iter_recurse(iter, &sub_iter); 58*2912Sartem r->argv = get_string_array(&sub_iter, NULL); 59*2912Sartem 60*2912Sartem return TRUE; 61*2912Sartem 62*2912Sartem malformed: 63*2912Sartem return FALSE; 64*2912Sartem } 65*2912Sartem 66*2912Sartem static void 67*2912Sartem handle_run(DBusConnection *con, DBusMessage *msg) 68*2912Sartem { 69*2912Sartem DBusMessage *reply; 70*2912Sartem DBusMessageIter iter; 71*2912Sartem run_request *r; 72*2912Sartem char *tmpstr; 73*2912Sartem 74*2912Sartem r = new_run_request(); 75*2912Sartem g_assert(dbus_message_iter_init(msg, &iter)); 76*2912Sartem 77*2912Sartem if (!parse_first_part(r, msg, &iter)) 78*2912Sartem goto malformed; 79*2912Sartem 80*2912Sartem /* Next a string of what should be written to stdin */ 81*2912Sartem if (!dbus_message_iter_next(&iter) || dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) 82*2912Sartem goto malformed; 83*2912Sartem dbus_message_iter_get_basic(&iter, &tmpstr); 84*2912Sartem r->input = g_strdup(tmpstr); 85*2912Sartem 86*2912Sartem /* Then an bool to indicate if we should grab stderr */ 87*2912Sartem if (!dbus_message_iter_next(&iter) || dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN) 88*2912Sartem goto malformed; 89*2912Sartem dbus_message_iter_get_basic(&iter, &(r->error_on_stderr)); 90*2912Sartem 91*2912Sartem /* Then an uint32 timeout for it */ 92*2912Sartem if (!dbus_message_iter_next(&iter) || dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32) 93*2912Sartem goto malformed; 94*2912Sartem dbus_message_iter_get_basic(&iter, &(r->timeout)); 95*2912Sartem 96*2912Sartem /* let run_request_run handle the reply */ 97*2912Sartem run_request_run(r, con, msg, NULL); 98*2912Sartem return; 99*2912Sartem 100*2912Sartem malformed: 101*2912Sartem del_run_request(r); 102*2912Sartem reply = dbus_message_new_error(msg, "org.freedesktop.HalRunner.Malformed", 103*2912Sartem "Malformed run request"); 104*2912Sartem dbus_connection_send(con, reply, NULL); 105*2912Sartem dbus_message_unref(reply); 106*2912Sartem } 107*2912Sartem 108*2912Sartem static void 109*2912Sartem handle_start(DBusConnection *con, DBusMessage *msg) 110*2912Sartem { 111*2912Sartem DBusMessage *reply; 112*2912Sartem DBusMessageIter iter; 113*2912Sartem run_request *r; 114*2912Sartem GPid pid; 115*2912Sartem 116*2912Sartem r = new_run_request(); 117*2912Sartem g_assert(dbus_message_iter_init(msg, &iter)); 118*2912Sartem 119*2912Sartem if (!dbus_message_iter_init(msg, &iter) || !parse_first_part(r, msg, &iter)) 120*2912Sartem goto malformed; 121*2912Sartem 122*2912Sartem if (run_request_run(r, con, NULL, &pid)) { 123*2912Sartem reply = dbus_message_new_method_return(msg); 124*2912Sartem dbus_message_append_args (reply, 125*2912Sartem DBUS_TYPE_INT64, &pid, 126*2912Sartem DBUS_TYPE_INVALID); 127*2912Sartem 128*2912Sartem } else { 129*2912Sartem reply = dbus_message_new_error(msg, "org.freedesktop.HalRunner.Failed", 130*2912Sartem "Start request failed"); 131*2912Sartem } 132*2912Sartem dbus_connection_send(con, reply, NULL); 133*2912Sartem dbus_message_unref(reply); 134*2912Sartem return ; 135*2912Sartem malformed: 136*2912Sartem del_run_request(r); 137*2912Sartem reply = dbus_message_new_error(msg, "org.freedesktop.HalRunner.Malformed", 138*2912Sartem "Malformed start request"); 139*2912Sartem dbus_connection_send(con, reply, NULL); 140*2912Sartem dbus_message_unref(reply); 141*2912Sartem } 142*2912Sartem 143*2912Sartem static void 144*2912Sartem handle_kill(DBusConnection *con, DBusMessage *msg) 145*2912Sartem { 146*2912Sartem DBusError error; 147*2912Sartem DBusMessage *reply = NULL; 148*2912Sartem char *udi; 149*2912Sartem 150*2912Sartem dbus_error_init (&error); 151*2912Sartem if (!dbus_message_get_args(msg, &error, 152*2912Sartem DBUS_TYPE_STRING, &udi, 153*2912Sartem DBUS_TYPE_INVALID)) { 154*2912Sartem reply = dbus_message_new_error (msg, "org.freedesktop.HalRunner.Malformed", 155*2912Sartem "Malformed kill message"); 156*2912Sartem g_assert(reply); 157*2912Sartem dbus_connection_send (con, reply, NULL); 158*2912Sartem dbus_message_unref(reply); 159*2912Sartem return; 160*2912Sartem } 161*2912Sartem run_kill_udi(udi); 162*2912Sartem 163*2912Sartem /* always successfull */ 164*2912Sartem reply = dbus_message_new_method_return(msg); 165*2912Sartem dbus_connection_send(con, reply, NULL); 166*2912Sartem dbus_message_unref(reply); 167*2912Sartem } 168*2912Sartem 169*2912Sartem static DBusHandlerResult 170*2912Sartem filter(DBusConnection *con, DBusMessage *msg, void *user_data) 171*2912Sartem { 172*2912Sartem DBusMessage *reply; 173*2912Sartem 174*2912Sartem if (dbus_message_is_method_call(msg, "org.freedesktop.HalRunner", "Run")) { 175*2912Sartem handle_run(con, msg); 176*2912Sartem return DBUS_HANDLER_RESULT_HANDLED; 177*2912Sartem } else if (dbus_message_is_method_call(msg, "org.freedesktop.HalRunner", "Start")) { 178*2912Sartem handle_start(con, msg); 179*2912Sartem return DBUS_HANDLER_RESULT_HANDLED; 180*2912Sartem } else if (dbus_message_is_method_call(msg, "org.freedesktop.HalRunner", "Kill")) { 181*2912Sartem handle_kill(con, msg); 182*2912Sartem return DBUS_HANDLER_RESULT_HANDLED; 183*2912Sartem } else if (dbus_message_is_method_call(msg, "org.freedesktop.HalRunner", "KillAll")) { 184*2912Sartem run_kill_all(); 185*2912Sartem /* alwasy successfull */ 186*2912Sartem reply = dbus_message_new_method_return(msg); 187*2912Sartem dbus_connection_send(con, reply, NULL); 188*2912Sartem dbus_message_unref(reply); 189*2912Sartem return DBUS_HANDLER_RESULT_HANDLED; 190*2912Sartem } 191*2912Sartem return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 192*2912Sartem } 193*2912Sartem 194*2912Sartem int 195*2912Sartem main(int argc, char **argv) 196*2912Sartem { 197*2912Sartem DBusConnection *c; 198*2912Sartem DBusError error; 199*2912Sartem GMainLoop *loop; 200*2912Sartem char *dbus_address; 201*2912Sartem 202*2912Sartem run_init(); 203*2912Sartem dbus_error_init(&error); 204*2912Sartem dbus_address = getenv("HALD_RUNNER_DBUS_ADDRESS"); 205*2912Sartem g_assert(dbus_address != NULL); 206*2912Sartem 207*2912Sartem fprintf(stderr, "Runner started - allowed paths are '%s'\n", getenv("PATH")); 208*2912Sartem 209*2912Sartem c = dbus_connection_open(dbus_address, &error); 210*2912Sartem if (c == NULL) 211*2912Sartem goto error; 212*2912Sartem 213*2912Sartem loop = g_main_loop_new(NULL, FALSE); 214*2912Sartem 215*2912Sartem dbus_connection_setup_with_g_main(c, NULL); 216*2912Sartem dbus_connection_set_exit_on_disconnect(c, TRUE); 217*2912Sartem dbus_connection_add_filter(c, filter, NULL, NULL); 218*2912Sartem 219*2912Sartem g_main_loop_run(loop); 220*2912Sartem 221*2912Sartem error: 222*2912Sartem fprintf(stderr,"An error has occured: %s\n", error.message); 223*2912Sartem return -1; 224*2912Sartem } 225