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 dbus_int64_t pid64; 116 117 r = new_run_request(); 118 g_assert(dbus_message_iter_init(msg, &iter)); 119 120 if (!dbus_message_iter_init(msg, &iter) || !parse_first_part(r, msg, &iter)) 121 goto malformed; 122 123 if (run_request_run(r, con, NULL, &pid)) { 124 pid64 = pid; 125 reply = dbus_message_new_method_return(msg); 126 dbus_message_append_args (reply, 127 DBUS_TYPE_INT64, &pid64, 128 DBUS_TYPE_INVALID); 129 130 } else { 131 reply = dbus_message_new_error(msg, "org.freedesktop.HalRunner.Failed", 132 "Start request failed"); 133 } 134 dbus_connection_send(con, reply, NULL); 135 dbus_message_unref(reply); 136 return ; 137 malformed: 138 del_run_request(r); 139 reply = dbus_message_new_error(msg, "org.freedesktop.HalRunner.Malformed", 140 "Malformed start request"); 141 dbus_connection_send(con, reply, NULL); 142 dbus_message_unref(reply); 143 } 144 145 static void 146 handle_kill(DBusConnection *con, DBusMessage *msg) 147 { 148 DBusError error; 149 DBusMessage *reply = NULL; 150 char *udi; 151 152 dbus_error_init (&error); 153 if (!dbus_message_get_args(msg, &error, 154 DBUS_TYPE_STRING, &udi, 155 DBUS_TYPE_INVALID)) { 156 reply = dbus_message_new_error (msg, "org.freedesktop.HalRunner.Malformed", 157 "Malformed kill message"); 158 g_assert(reply); 159 dbus_connection_send (con, reply, NULL); 160 dbus_message_unref(reply); 161 return; 162 } 163 run_kill_udi(udi); 164 165 /* always successfull */ 166 reply = dbus_message_new_method_return(msg); 167 dbus_connection_send(con, reply, NULL); 168 dbus_message_unref(reply); 169 } 170 171 static DBusHandlerResult 172 filter(DBusConnection *con, DBusMessage *msg, void *user_data) 173 { 174 DBusMessage *reply; 175 176 if (dbus_message_is_method_call(msg, "org.freedesktop.HalRunner", "Run")) { 177 handle_run(con, msg); 178 return DBUS_HANDLER_RESULT_HANDLED; 179 } else if (dbus_message_is_method_call(msg, "org.freedesktop.HalRunner", "Start")) { 180 handle_start(con, msg); 181 return DBUS_HANDLER_RESULT_HANDLED; 182 } else if (dbus_message_is_method_call(msg, "org.freedesktop.HalRunner", "Kill")) { 183 handle_kill(con, msg); 184 return DBUS_HANDLER_RESULT_HANDLED; 185 } else if (dbus_message_is_method_call(msg, "org.freedesktop.HalRunner", "KillAll")) { 186 run_kill_all(); 187 /* alwasy successfull */ 188 reply = dbus_message_new_method_return(msg); 189 dbus_connection_send(con, reply, NULL); 190 dbus_message_unref(reply); 191 return DBUS_HANDLER_RESULT_HANDLED; 192 } 193 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 194 } 195 196 int 197 main(int argc, char **argv) 198 { 199 DBusConnection *c; 200 DBusError error; 201 GMainLoop *loop; 202 char *dbus_address; 203 204 run_init(); 205 dbus_error_init(&error); 206 dbus_address = getenv("HALD_RUNNER_DBUS_ADDRESS"); 207 g_assert(dbus_address != NULL); 208 209 fprintf(stderr, "Runner started - allowed paths are '%s'\n", getenv("PATH")); 210 211 c = dbus_connection_open(dbus_address, &error); 212 if (c == NULL) 213 goto error; 214 215 loop = g_main_loop_new(NULL, FALSE); 216 217 dbus_connection_setup_with_g_main(c, NULL); 218 dbus_connection_set_exit_on_disconnect(c, TRUE); 219 dbus_connection_add_filter(c, filter, NULL, NULL); 220 221 g_main_loop_run(loop); 222 223 error: 224 fprintf(stderr,"An error has occured: %s\n", error.message); 225 return -1; 226 } 227