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