main.c revision 3168:18866604610a
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
34static gboolean
35parse_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
62malformed:
63	return FALSE;
64}
65
66static void
67handle_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
100malformed:
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
108static void
109handle_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 ;
137malformed:
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
145static void
146handle_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
171static DBusHandlerResult
172filter(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
196int
197main(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
223error:
224	fprintf(stderr,"An error has occured: %s\n", error.message);
225	return -1;
226}
227