xref: /illumos-gate/usr/src/cmd/hal/hald-runner/main.c (revision 55fea89d)
118c2aff7Sartem /***************************************************************************
218c2aff7Sartem  * CVSID: $Id$
318c2aff7Sartem  *
418c2aff7Sartem  * main.c - Main dbus interface of the hald runner
518c2aff7Sartem  *
618c2aff7Sartem  * Copyright (C) 2006 Sjoerd Simons, <sjoerd@luon.net>
73ab06c27SMilan Jurik  * Copyright (C) 2007 Codethink Ltd. Author Rob Taylor <rob.taylor@codethink.co.uk>
818c2aff7Sartem  *
918c2aff7Sartem  * Licensed under the Academic Free License version 2.1
1018c2aff7Sartem  *
1118c2aff7Sartem  * This program is free software; you can redistribute it and/or modify
1218c2aff7Sartem  * it under the terms of the GNU General Public License as published by
1318c2aff7Sartem  * the Free Software Foundation; either version 2 of the License, or
1418c2aff7Sartem  * (at your option) any later version.
1518c2aff7Sartem  *
1618c2aff7Sartem  * This program is distributed in the hope that it will be useful,
1718c2aff7Sartem  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1818c2aff7Sartem  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1918c2aff7Sartem  * GNU General Public License for more details.
2018c2aff7Sartem  *
2118c2aff7Sartem  * You should have received a copy of the GNU General Public License
2218c2aff7Sartem  * along with this program; if not, write to the Free Software
2318c2aff7Sartem  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
2418c2aff7Sartem  *
2518c2aff7Sartem  **************************************************************************/
2618c2aff7Sartem #include <stdio.h>
2718c2aff7Sartem #include <stdlib.h>
28*55fea89dSDan Cross #define DBUS_API_SUBJECT_TO_CHANGE
2918c2aff7Sartem #include <dbus/dbus-glib-lowlevel.h>
3018c2aff7Sartem 
3118c2aff7Sartem #include <glib.h>
3218c2aff7Sartem #include "utils.h"
3318c2aff7Sartem #include "runner.h"
3418c2aff7Sartem 
353ab06c27SMilan Jurik #ifndef __GNUC__
363ab06c27SMilan Jurik #define __attribute__(x)
373ab06c27SMilan Jurik #endif
383ab06c27SMilan Jurik 
3918c2aff7Sartem static gboolean
parse_udi(run_request * r,DBusMessage * msg,DBusMessageIter * iter)403ab06c27SMilan Jurik parse_udi (run_request *r, DBusMessage *msg, DBusMessageIter *iter)
4118c2aff7Sartem {
4218c2aff7Sartem 	char *tmpstr;
4318c2aff7Sartem 
443ab06c27SMilan Jurik 	/* Should be the device UDI */
45*55fea89dSDan Cross 	if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING)
4618c2aff7Sartem 		goto malformed;
4718c2aff7Sartem 	dbus_message_iter_get_basic(iter, &tmpstr);
4818c2aff7Sartem 	r->udi = g_strdup(tmpstr);
4918c2aff7Sartem 
503ab06c27SMilan Jurik 	if (!dbus_message_iter_next(iter))
513ab06c27SMilan Jurik 		goto malformed;
523ab06c27SMilan Jurik 
533ab06c27SMilan Jurik 	return TRUE;
543ab06c27SMilan Jurik 
553ab06c27SMilan Jurik malformed:
563ab06c27SMilan Jurik 	return FALSE;
573ab06c27SMilan Jurik }
583ab06c27SMilan Jurik 
593ab06c27SMilan Jurik static gboolean
parse_environment(run_request * r,DBusMessage * msg,DBusMessageIter * iter)603ab06c27SMilan Jurik parse_environment(run_request *r, DBusMessage *msg, DBusMessageIter *iter)
613ab06c27SMilan Jurik {
623ab06c27SMilan Jurik 	DBusMessageIter sub_iter;
633ab06c27SMilan Jurik 	char *tmpstr;
643ab06c27SMilan Jurik 
653ab06c27SMilan Jurik 	/* The environment array */
663ab06c27SMilan Jurik 	if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
6718c2aff7Sartem 		goto malformed;
6818c2aff7Sartem 	dbus_message_iter_recurse(iter, &sub_iter);
6918c2aff7Sartem 	/* Add default path for the programs we start */
703ab06c27SMilan Jurik #if defined(__FreeBSD__)
713ab06c27SMilan Jurik 	tmpstr = g_strdup_printf("PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/sbin:/usr/X11R6/sbin:/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin:%s", getenv("PATH"));
723ab06c27SMilan Jurik #else
7318c2aff7Sartem 	tmpstr = g_strdup_printf("PATH=/sbin:/usr/sbin:/bin:/usr/bin:%s", getenv("PATH"));
743ab06c27SMilan Jurik #endif
7518c2aff7Sartem 	r->environment = get_string_array(&sub_iter, tmpstr);
7618c2aff7Sartem 
7718c2aff7Sartem 	/* Then argv */
78*55fea89dSDan Cross 	if (!dbus_message_iter_next(iter) || dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
7918c2aff7Sartem 		goto malformed;
8018c2aff7Sartem 	dbus_message_iter_recurse(iter, &sub_iter);
8118c2aff7Sartem 	r->argv = get_string_array(&sub_iter, NULL);
8218c2aff7Sartem 
8318c2aff7Sartem 	return TRUE;
8418c2aff7Sartem 
8518c2aff7Sartem malformed:
8618c2aff7Sartem 	return FALSE;
8718c2aff7Sartem }
8818c2aff7Sartem 
8918c2aff7Sartem static void
handle_run(DBusConnection * con,DBusMessage * msg)9018c2aff7Sartem handle_run(DBusConnection *con, DBusMessage *msg)
9118c2aff7Sartem {
9218c2aff7Sartem 	DBusMessage *reply;
9318c2aff7Sartem 	DBusMessageIter iter;
9418c2aff7Sartem 	run_request *r;
9518c2aff7Sartem 	char *tmpstr;
9618c2aff7Sartem 
9718c2aff7Sartem 	r = new_run_request();
9818c2aff7Sartem 	g_assert(dbus_message_iter_init(msg, &iter));
9918c2aff7Sartem 
1003ab06c27SMilan Jurik 	if (!parse_udi(r, msg, &iter))
1013ab06c27SMilan Jurik 		goto malformed;
1023ab06c27SMilan Jurik 
1033ab06c27SMilan Jurik 	if (!parse_environment(r, msg, &iter))
10418c2aff7Sartem 		goto malformed;
10518c2aff7Sartem 
10618c2aff7Sartem 	/* Next a string of what should be written to stdin */
10718c2aff7Sartem 	if (!dbus_message_iter_next(&iter) || dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
10818c2aff7Sartem 		goto malformed;
10918c2aff7Sartem 	dbus_message_iter_get_basic(&iter, &tmpstr);
11018c2aff7Sartem 	r->input = g_strdup(tmpstr);
11118c2aff7Sartem 
11218c2aff7Sartem 	/* Then an bool to indicate if we should grab stderr */
113*55fea89dSDan Cross 	if (!dbus_message_iter_next(&iter) || dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN)
11418c2aff7Sartem 		goto malformed;
11518c2aff7Sartem 	dbus_message_iter_get_basic(&iter, &(r->error_on_stderr));
11618c2aff7Sartem 
11718c2aff7Sartem 	/* Then an uint32 timeout for it */
118*55fea89dSDan Cross 	if (!dbus_message_iter_next(&iter) || dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
11918c2aff7Sartem 		goto malformed;
12018c2aff7Sartem 	dbus_message_iter_get_basic(&iter, &(r->timeout));
12118c2aff7Sartem 
12218c2aff7Sartem 	/* let run_request_run handle the reply */
12318c2aff7Sartem 	run_request_run(r, con, msg, NULL);
12418c2aff7Sartem 	return;
12518c2aff7Sartem 
12618c2aff7Sartem malformed:
12718c2aff7Sartem 	del_run_request(r);
12818c2aff7Sartem 	reply = dbus_message_new_error(msg, "org.freedesktop.HalRunner.Malformed",
12918c2aff7Sartem 				       "Malformed run request");
13018c2aff7Sartem 	dbus_connection_send(con, reply, NULL);
13118c2aff7Sartem 	dbus_message_unref(reply);
13218c2aff7Sartem }
13318c2aff7Sartem 
13418c2aff7Sartem static void
handle_start(DBusConnection * con,DBusMessage * msg,gboolean is_singleton)1353ab06c27SMilan Jurik handle_start(DBusConnection *con, DBusMessage *msg, gboolean is_singleton)
13618c2aff7Sartem {
13718c2aff7Sartem 	DBusMessage *reply;
13818c2aff7Sartem 	DBusMessageIter iter;
13918c2aff7Sartem 	run_request *r;
14018c2aff7Sartem 	GPid pid;
14118c2aff7Sartem 
14218c2aff7Sartem 	r = new_run_request();
1433ab06c27SMilan Jurik 	r->is_singleton = is_singleton;
1443ab06c27SMilan Jurik 
14518c2aff7Sartem 	g_assert(dbus_message_iter_init(msg, &iter));
14618c2aff7Sartem 
1473ab06c27SMilan Jurik 	if (!dbus_message_iter_init(msg, &iter))
14818c2aff7Sartem 		goto malformed;
14918c2aff7Sartem 
1503ab06c27SMilan Jurik 	if (!is_singleton && !parse_udi(r, msg, &iter)) {
1513ab06c27SMilan Jurik 		fprintf(stderr, "error parsing udi");
1523ab06c27SMilan Jurik 		goto malformed;
1533ab06c27SMilan Jurik 	}
1543ab06c27SMilan Jurik 
1553ab06c27SMilan Jurik 	if (!parse_environment(r, msg, &iter)) {
1563ab06c27SMilan Jurik 		fprintf(stderr, "error parsing environment");
1573ab06c27SMilan Jurik 		goto malformed;
1583ab06c27SMilan Jurik 	}
1593ab06c27SMilan Jurik 
16018c2aff7Sartem 	if (run_request_run(r, con, NULL, &pid)) {
1613ab06c27SMilan Jurik 		gint64 ppid = pid;
16218c2aff7Sartem 		reply = dbus_message_new_method_return(msg);
163*55fea89dSDan Cross 		dbus_message_append_args (reply,
1643ab06c27SMilan Jurik 					  DBUS_TYPE_INT64, &ppid,
16518c2aff7Sartem 					  DBUS_TYPE_INVALID);
166*55fea89dSDan Cross 
16718c2aff7Sartem 	} else {
16818c2aff7Sartem 		reply = dbus_message_new_error(msg, "org.freedesktop.HalRunner.Failed",
16918c2aff7Sartem 					       "Start request failed");
17018c2aff7Sartem 	}
17118c2aff7Sartem 	dbus_connection_send(con, reply, NULL);
17218c2aff7Sartem 	dbus_message_unref(reply);
17318c2aff7Sartem 	return ;
17418c2aff7Sartem malformed:
17518c2aff7Sartem 	del_run_request(r);
17618c2aff7Sartem 	reply = dbus_message_new_error(msg, "org.freedesktop.HalRunner.Malformed",
17718c2aff7Sartem 				       "Malformed start request");
17818c2aff7Sartem 	dbus_connection_send(con, reply, NULL);
17918c2aff7Sartem 	dbus_message_unref(reply);
18018c2aff7Sartem }
18118c2aff7Sartem 
18218c2aff7Sartem static void
handle_kill(DBusConnection * con,DBusMessage * msg)18318c2aff7Sartem handle_kill(DBusConnection *con, DBusMessage *msg)
18418c2aff7Sartem {
18518c2aff7Sartem 	DBusError error;
18618c2aff7Sartem 	DBusMessage *reply = NULL;
18718c2aff7Sartem 	char *udi;
18818c2aff7Sartem 
18918c2aff7Sartem 	dbus_error_init (&error);
19018c2aff7Sartem 	if (!dbus_message_get_args(msg, &error,
19118c2aff7Sartem 				   DBUS_TYPE_STRING, &udi,
19218c2aff7Sartem 				   DBUS_TYPE_INVALID)) {
193*55fea89dSDan Cross 		reply = dbus_message_new_error (msg, "org.freedesktop.HalRunner.Malformed",
19418c2aff7Sartem 						"Malformed kill message");
19518c2aff7Sartem 		g_assert(reply);
19618c2aff7Sartem 		dbus_connection_send (con, reply, NULL);
19718c2aff7Sartem 		dbus_message_unref(reply);
19818c2aff7Sartem 		return;
19918c2aff7Sartem 	}
20018c2aff7Sartem 	run_kill_udi(udi);
20118c2aff7Sartem 
20218c2aff7Sartem 	/* always successfull */
20318c2aff7Sartem 	reply = dbus_message_new_method_return(msg);
20418c2aff7Sartem 	dbus_connection_send(con, reply, NULL);
20518c2aff7Sartem 	dbus_message_unref(reply);
20618c2aff7Sartem }
20718c2aff7Sartem 
20818c2aff7Sartem static DBusHandlerResult
filter(DBusConnection * con,DBusMessage * msg,void * user_data)20918c2aff7Sartem filter(DBusConnection *con, DBusMessage *msg, void *user_data)
21018c2aff7Sartem {
21118c2aff7Sartem 	DBusMessage *reply;
21218c2aff7Sartem 
21318c2aff7Sartem 	if (dbus_message_is_method_call(msg, "org.freedesktop.HalRunner", "Run")) {
21418c2aff7Sartem 		handle_run(con, msg);
21518c2aff7Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
21618c2aff7Sartem 	} else if (dbus_message_is_method_call(msg, "org.freedesktop.HalRunner", "Start")) {
2173ab06c27SMilan Jurik 		handle_start(con, msg, FALSE);
2183ab06c27SMilan Jurik 		return DBUS_HANDLER_RESULT_HANDLED;
2193ab06c27SMilan Jurik 	} else if (dbus_message_is_method_call(msg, "org.freedesktop.HalRunner", "StartSingleton")) {
2203ab06c27SMilan Jurik 		handle_start(con, msg, TRUE);
22118c2aff7Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
22218c2aff7Sartem 	} else if (dbus_message_is_method_call(msg, "org.freedesktop.HalRunner", "Kill")) {
22318c2aff7Sartem 		handle_kill(con, msg);
22418c2aff7Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
2253ab06c27SMilan Jurik 	} else if (dbus_message_is_method_call(msg, "org.freedesktop.HalRunner", "Shutdown")) {
2263ab06c27SMilan Jurik 		run_kill_all ();
2273ab06c27SMilan Jurik 		exit (0);
2283ab06c27SMilan Jurik 		return DBUS_HANDLER_RESULT_HANDLED;
22918c2aff7Sartem 	} else if (dbus_message_is_method_call(msg, "org.freedesktop.HalRunner", "KillAll")) {
23018c2aff7Sartem 		run_kill_all();
23118c2aff7Sartem 		/* alwasy successfull */
23218c2aff7Sartem 		reply = dbus_message_new_method_return(msg);
23318c2aff7Sartem 		dbus_connection_send(con, reply, NULL);
23418c2aff7Sartem 		dbus_message_unref(reply);
23518c2aff7Sartem 		return DBUS_HANDLER_RESULT_HANDLED;
23618c2aff7Sartem 	}
23718c2aff7Sartem 	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
23818c2aff7Sartem }
23918c2aff7Sartem 
24018c2aff7Sartem int
main(int argc,char ** argv)24118c2aff7Sartem main(int argc, char **argv)
24218c2aff7Sartem {
24318c2aff7Sartem 	DBusConnection *c;
24418c2aff7Sartem 	DBusError error;
24518c2aff7Sartem 	GMainLoop *loop;
24618c2aff7Sartem 	char *dbus_address;
24718c2aff7Sartem 
24818c2aff7Sartem 	run_init();
24918c2aff7Sartem 	dbus_error_init(&error);
25018c2aff7Sartem 	dbus_address = getenv("HALD_RUNNER_DBUS_ADDRESS");
25118c2aff7Sartem 	g_assert(dbus_address != NULL);
25218c2aff7Sartem 
25318c2aff7Sartem 	fprintf(stderr, "Runner started - allowed paths are '%s'\n", getenv("PATH"));
25418c2aff7Sartem 
25518c2aff7Sartem 	c = dbus_connection_open(dbus_address, &error);
25618c2aff7Sartem 	if (c == NULL)
25718c2aff7Sartem 		goto error;
25818c2aff7Sartem 
25918c2aff7Sartem 	loop = g_main_loop_new(NULL, FALSE);
26018c2aff7Sartem 
26118c2aff7Sartem 	dbus_connection_setup_with_g_main(c, NULL);
26218c2aff7Sartem 	dbus_connection_set_exit_on_disconnect(c, TRUE);
26318c2aff7Sartem 	dbus_connection_add_filter(c, filter, NULL, NULL);
26418c2aff7Sartem 
26518c2aff7Sartem 	g_main_loop_run(loop);
26618c2aff7Sartem 
26718c2aff7Sartem error:
26818c2aff7Sartem 	fprintf(stderr,"An error has occured: %s\n", error.message);
26918c2aff7Sartem 	return -1;
27018c2aff7Sartem }
271