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