12912Sartem /***************************************************************************
22912Sartem * CVSID: $Id$
32912Sartem *
42912Sartem * main.c - Main dbus interface of the hald runner
52912Sartem *
62912Sartem * Copyright (C) 2006 Sjoerd Simons, <sjoerd@luon.net>
72912Sartem *
82912Sartem * Licensed under the Academic Free License version 2.1
92912Sartem *
102912Sartem * This program is free software; you can redistribute it and/or modify
112912Sartem * it under the terms of the GNU General Public License as published by
122912Sartem * the Free Software Foundation; either version 2 of the License, or
132912Sartem * (at your option) any later version.
142912Sartem *
152912Sartem * This program is distributed in the hope that it will be useful,
162912Sartem * but WITHOUT ANY WARRANTY; without even the implied warranty of
172912Sartem * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
182912Sartem * GNU General Public License for more details.
192912Sartem *
202912Sartem * You should have received a copy of the GNU General Public License
212912Sartem * along with this program; if not, write to the Free Software
222912Sartem * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
232912Sartem *
242912Sartem **************************************************************************/
252912Sartem #include <stdio.h>
262912Sartem #include <stdlib.h>
272912Sartem #define DBUS_API_SUBJECT_TO_CHANGE
282912Sartem #include <dbus/dbus-glib-lowlevel.h>
292912Sartem
302912Sartem #include <glib.h>
312912Sartem #include "utils.h"
322912Sartem #include "runner.h"
332912Sartem
342912Sartem static gboolean
parse_first_part(run_request * r,DBusMessage * msg,DBusMessageIter * iter)352912Sartem parse_first_part(run_request *r, DBusMessage *msg, DBusMessageIter *iter)
362912Sartem {
372912Sartem DBusMessageIter sub_iter;
382912Sartem char *tmpstr;
392912Sartem
402912Sartem /* First should be the device UDI */
412912Sartem if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING)
422912Sartem goto malformed;
432912Sartem dbus_message_iter_get_basic(iter, &tmpstr);
442912Sartem r->udi = g_strdup(tmpstr);
452912Sartem
462912Sartem /* Then the environment array */
472912Sartem if (!dbus_message_iter_next(iter) || dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
482912Sartem goto malformed;
492912Sartem dbus_message_iter_recurse(iter, &sub_iter);
502912Sartem /* Add default path for the programs we start */
512912Sartem tmpstr = g_strdup_printf("PATH=/sbin:/usr/sbin:/bin:/usr/bin:%s", getenv("PATH"));
522912Sartem r->environment = get_string_array(&sub_iter, tmpstr);
532912Sartem
542912Sartem /* Then argv */
552912Sartem if (!dbus_message_iter_next(iter) || dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
562912Sartem goto malformed;
572912Sartem dbus_message_iter_recurse(iter, &sub_iter);
582912Sartem r->argv = get_string_array(&sub_iter, NULL);
592912Sartem
602912Sartem return TRUE;
612912Sartem
622912Sartem malformed:
632912Sartem return FALSE;
642912Sartem }
652912Sartem
662912Sartem static void
handle_run(DBusConnection * con,DBusMessage * msg)672912Sartem handle_run(DBusConnection *con, DBusMessage *msg)
682912Sartem {
692912Sartem DBusMessage *reply;
702912Sartem DBusMessageIter iter;
712912Sartem run_request *r;
722912Sartem char *tmpstr;
732912Sartem
742912Sartem r = new_run_request();
752912Sartem g_assert(dbus_message_iter_init(msg, &iter));
762912Sartem
772912Sartem if (!parse_first_part(r, msg, &iter))
782912Sartem goto malformed;
792912Sartem
802912Sartem /* Next a string of what should be written to stdin */
812912Sartem if (!dbus_message_iter_next(&iter) || dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
822912Sartem goto malformed;
832912Sartem dbus_message_iter_get_basic(&iter, &tmpstr);
842912Sartem r->input = g_strdup(tmpstr);
852912Sartem
862912Sartem /* Then an bool to indicate if we should grab stderr */
872912Sartem if (!dbus_message_iter_next(&iter) || dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN)
882912Sartem goto malformed;
892912Sartem dbus_message_iter_get_basic(&iter, &(r->error_on_stderr));
902912Sartem
912912Sartem /* Then an uint32 timeout for it */
922912Sartem if (!dbus_message_iter_next(&iter) || dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
932912Sartem goto malformed;
942912Sartem dbus_message_iter_get_basic(&iter, &(r->timeout));
952912Sartem
962912Sartem /* let run_request_run handle the reply */
972912Sartem run_request_run(r, con, msg, NULL);
982912Sartem return;
992912Sartem
1002912Sartem malformed:
1012912Sartem del_run_request(r);
1022912Sartem reply = dbus_message_new_error(msg, "org.freedesktop.HalRunner.Malformed",
1032912Sartem "Malformed run request");
1042912Sartem dbus_connection_send(con, reply, NULL);
1052912Sartem dbus_message_unref(reply);
1062912Sartem }
1072912Sartem
1082912Sartem static void
handle_start(DBusConnection * con,DBusMessage * msg)1092912Sartem handle_start(DBusConnection *con, DBusMessage *msg)
1102912Sartem {
1112912Sartem DBusMessage *reply;
1122912Sartem DBusMessageIter iter;
1132912Sartem run_request *r;
1142912Sartem GPid pid;
115*3168Sartem dbus_int64_t pid64;
1162912Sartem
1172912Sartem r = new_run_request();
1182912Sartem g_assert(dbus_message_iter_init(msg, &iter));
1192912Sartem
1202912Sartem if (!dbus_message_iter_init(msg, &iter) || !parse_first_part(r, msg, &iter))
1212912Sartem goto malformed;
1222912Sartem
1232912Sartem if (run_request_run(r, con, NULL, &pid)) {
124*3168Sartem pid64 = pid;
1252912Sartem reply = dbus_message_new_method_return(msg);
1262912Sartem dbus_message_append_args (reply,
127*3168Sartem DBUS_TYPE_INT64, &pid64,
1282912Sartem DBUS_TYPE_INVALID);
1292912Sartem
1302912Sartem } else {
1312912Sartem reply = dbus_message_new_error(msg, "org.freedesktop.HalRunner.Failed",
1322912Sartem "Start request failed");
1332912Sartem }
1342912Sartem dbus_connection_send(con, reply, NULL);
1352912Sartem dbus_message_unref(reply);
1362912Sartem return ;
1372912Sartem malformed:
1382912Sartem del_run_request(r);
1392912Sartem reply = dbus_message_new_error(msg, "org.freedesktop.HalRunner.Malformed",
1402912Sartem "Malformed start request");
1412912Sartem dbus_connection_send(con, reply, NULL);
1422912Sartem dbus_message_unref(reply);
1432912Sartem }
1442912Sartem
1452912Sartem static void
handle_kill(DBusConnection * con,DBusMessage * msg)1462912Sartem handle_kill(DBusConnection *con, DBusMessage *msg)
1472912Sartem {
1482912Sartem DBusError error;
1492912Sartem DBusMessage *reply = NULL;
1502912Sartem char *udi;
1512912Sartem
1522912Sartem dbus_error_init (&error);
1532912Sartem if (!dbus_message_get_args(msg, &error,
1542912Sartem DBUS_TYPE_STRING, &udi,
1552912Sartem DBUS_TYPE_INVALID)) {
1562912Sartem reply = dbus_message_new_error (msg, "org.freedesktop.HalRunner.Malformed",
1572912Sartem "Malformed kill message");
1582912Sartem g_assert(reply);
1592912Sartem dbus_connection_send (con, reply, NULL);
1602912Sartem dbus_message_unref(reply);
1612912Sartem return;
1622912Sartem }
1632912Sartem run_kill_udi(udi);
1642912Sartem
1652912Sartem /* always successfull */
1662912Sartem reply = dbus_message_new_method_return(msg);
1672912Sartem dbus_connection_send(con, reply, NULL);
1682912Sartem dbus_message_unref(reply);
1692912Sartem }
1702912Sartem
1712912Sartem static DBusHandlerResult
filter(DBusConnection * con,DBusMessage * msg,void * user_data)1722912Sartem filter(DBusConnection *con, DBusMessage *msg, void *user_data)
1732912Sartem {
1742912Sartem DBusMessage *reply;
1752912Sartem
1762912Sartem if (dbus_message_is_method_call(msg, "org.freedesktop.HalRunner", "Run")) {
1772912Sartem handle_run(con, msg);
1782912Sartem return DBUS_HANDLER_RESULT_HANDLED;
1792912Sartem } else if (dbus_message_is_method_call(msg, "org.freedesktop.HalRunner", "Start")) {
1802912Sartem handle_start(con, msg);
1812912Sartem return DBUS_HANDLER_RESULT_HANDLED;
1822912Sartem } else if (dbus_message_is_method_call(msg, "org.freedesktop.HalRunner", "Kill")) {
1832912Sartem handle_kill(con, msg);
1842912Sartem return DBUS_HANDLER_RESULT_HANDLED;
1852912Sartem } else if (dbus_message_is_method_call(msg, "org.freedesktop.HalRunner", "KillAll")) {
1862912Sartem run_kill_all();
1872912Sartem /* alwasy successfull */
1882912Sartem reply = dbus_message_new_method_return(msg);
1892912Sartem dbus_connection_send(con, reply, NULL);
1902912Sartem dbus_message_unref(reply);
1912912Sartem return DBUS_HANDLER_RESULT_HANDLED;
1922912Sartem }
1932912Sartem return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1942912Sartem }
1952912Sartem
1962912Sartem int
main(int argc,char ** argv)1972912Sartem main(int argc, char **argv)
1982912Sartem {
1992912Sartem DBusConnection *c;
2002912Sartem DBusError error;
2012912Sartem GMainLoop *loop;
2022912Sartem char *dbus_address;
2032912Sartem
2042912Sartem run_init();
2052912Sartem dbus_error_init(&error);
2062912Sartem dbus_address = getenv("HALD_RUNNER_DBUS_ADDRESS");
2072912Sartem g_assert(dbus_address != NULL);
2082912Sartem
2092912Sartem fprintf(stderr, "Runner started - allowed paths are '%s'\n", getenv("PATH"));
2102912Sartem
2112912Sartem c = dbus_connection_open(dbus_address, &error);
2122912Sartem if (c == NULL)
2132912Sartem goto error;
2142912Sartem
2152912Sartem loop = g_main_loop_new(NULL, FALSE);
2162912Sartem
2172912Sartem dbus_connection_setup_with_g_main(c, NULL);
2182912Sartem dbus_connection_set_exit_on_disconnect(c, TRUE);
2192912Sartem dbus_connection_add_filter(c, filter, NULL, NULL);
2202912Sartem
2212912Sartem g_main_loop_run(loop);
2222912Sartem
2232912Sartem error:
2242912Sartem fprintf(stderr,"An error has occured: %s\n", error.message);
2252912Sartem return -1;
2262912Sartem }
227