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