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