From: Jonathan Maw Date: Mon, 9 Jul 2012 15:15:07 +0000 (+0100) Subject: Rewrite legacy app handler's command-line to use D-Bus X-Git-Tag: node-startup-controller-0.9.1~124^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a077d424287efd8d82f03f5d5c31c2ec7f695d9a;p=profile%2Fivi%2Fnode-startup-controller.git Rewrite legacy app handler's command-line to use D-Bus The GApplication object's command-line method does not work when the application is running on the system bus. The solution is to use D-Bus calls to communicate with the primary instance instead. If the executable is called with command-line arguments, instead of starting a GApplication it calls the Register() and Deregister() methods instead. This commit also adds all the necessary changes so that the legacy app handler can be D-Bus activated on the system bus and started with systemd. --- diff --git a/configure.ac b/configure.ac index 9e16a83..7f25c54 100644 --- a/configure.ac +++ b/configure.ac @@ -137,7 +137,9 @@ AC_OUTPUT([ Makefile common/Makefile boot-manager/Makefile +legacy-app-handler/dbus/Makefile legacy-app-handler/Makefile +legacy-app-handler/systemd/Makefile luc-handler/Makefile luc-handler/org.genivi.LUCHandler1.gschema.xml tests/Makefile diff --git a/legacy-app-handler/Makefile.am b/legacy-app-handler/Makefile.am index 9ac1c0c..0e037bc 100644 --- a/legacy-app-handler/Makefile.am +++ b/legacy-app-handler/Makefile.am @@ -1,5 +1,9 @@ # vi:set ts=8 sw=8 noet ai nocindent: +SUBDIRS = \ + dbus \ + systemd + legacy_app_handler_confdir = /etc/dbus-1/system.d legacy_app_handler_conf_DATA = \ @@ -52,21 +56,7 @@ legacy_app_handler_LDADD = \ $(SYSTEMD_DAEMON_LIBS) \ $(top_builddir)/common/libcommon.la -servicedir = $(datadir)/dbus-1/services -service_in_files = \ - org.genivi.LegacyAppHandler1.service.in - -service_DATA = $(service_in_files:.service.in=.service) - -%.service: %.service.in - sed -e "s,\@libdir\@,$(libdir),g" \ - -e "s,\@BOOT_MANAGER_VERSION_API\@,$(BOOT_MANAGER_VERSION_API),g" < $< > $@ - -CLEANFILES = \ - $(service_DATA) - EXTRA_DIST = \ - $(service_in_files) \ $(gsettingsschema_in_files) \ la-handler-dbus.xml diff --git a/legacy-app-handler/dbus/Makefile.am b/legacy-app-handler/dbus/Makefile.am new file mode 100644 index 0000000..1ba7717 --- /dev/null +++ b/legacy-app-handler/dbus/Makefile.am @@ -0,0 +1,20 @@ +# vi:set ts=8 sw=8 noet ai nocindent: + +bus_servicedir = $(datadir)/dbus-1/system-services + +bus_service_in_files = \ + org.genivi.LegacyAppHandler1.service.in + +bus_service_DATA = $(bus_service_in_files:.service.in=.service) + +%.service: %.service.in + sed -e "s,\@libdir\@,$(libdir),g" \ + -e "s,\@BOOT_MANAGER_VERSION_API\@,$(BOOT_MANAGER_VERSION_API),g" < $< > $@ + +CLEANFILES = \ + $(bus_service_DATA) + +EXTRA_DIST = \ + $(bus_service_in_files) + + diff --git a/legacy-app-handler/org.genivi.LegacyAppHandler1.service.in b/legacy-app-handler/dbus/org.genivi.LegacyAppHandler1.service.in similarity index 70% rename from legacy-app-handler/org.genivi.LegacyAppHandler1.service.in rename to legacy-app-handler/dbus/org.genivi.LegacyAppHandler1.service.in index ac52817..3d84a65 100644 --- a/legacy-app-handler/org.genivi.LegacyAppHandler1.service.in +++ b/legacy-app-handler/dbus/org.genivi.LegacyAppHandler1.service.in @@ -1,3 +1,4 @@ [D-BUS Service] Name=org.genivi.LegacyAppHandler1 +SystemdService = org.genivi.LegacyAppHandler1.service Exec=@libdir@/legacy-app-handler-@BOOT_MANAGER_VERSION_API@/legacy-app-handler diff --git a/legacy-app-handler/la-handler-application.c b/legacy-app-handler/la-handler-application.c index 7352b80..05b9167 100644 --- a/legacy-app-handler/la-handler-application.c +++ b/legacy-app-handler/la-handler-application.c @@ -51,8 +51,6 @@ static void la_handler_application_set_property (GObject *object const GValue *value, GParamSpec *pspec); static void la_handler_application_startup (GApplication *application); -static int la_handler_application_command_line (GApplication *application, - GApplicationCommandLine *cmdline); @@ -92,7 +90,6 @@ la_handler_application_class_init (LAHandlerApplicationClass *klass) gapplication_class = G_APPLICATION_CLASS (klass); gapplication_class->startup = la_handler_application_startup; - gapplication_class->command_line = la_handler_application_command_line; g_object_class_install_property (gobject_class, PROP_LA_HANDLER_SERVICE, @@ -192,88 +189,6 @@ la_handler_application_startup (GApplication *app) -static int -la_handler_application_command_line (GApplication *application, - GApplicationCommandLine *cmdline) -{ - GOptionContext *context; - gboolean do_register; - GError *error = NULL; - gchar **args; - gchar **argv; - gchar *mode = NULL; - gchar *unit = NULL; - gint argc; - gint timeout = 0; - gint i; - - GOptionEntry entries[] = { - {"register", 0, 0, G_OPTION_ARG_NONE, &do_register, NULL, NULL}, - {"unit", 0, 0, G_OPTION_ARG_STRING, &unit, NULL, NULL}, - {"timeout", 0, 0, G_OPTION_ARG_INT, &timeout, NULL, NULL}, - {"shutdown-mode", 0, 0, G_OPTION_ARG_STRING, &mode, NULL, NULL}, - {NULL}, - }; - - /* keep the application running until we have finished */ - g_application_hold (application); - - /* retrieve the command-line arguments */ - args = g_application_command_line_get_arguments (cmdline, &argc); - - /* copy the args array, because g_option_context_parse() removes elements without - * freeing them */ - argv = g_new (gchar *, argc + 1); - for (i = 0; i <= argc; i++) - argv[i] = args[i]; - - /* set up the option context */ - context = g_option_context_new (NULL); - g_option_context_set_help_enabled (context, FALSE); - g_option_context_add_main_entries (context, entries, NULL); - - /* parse the arguments into the argument data */ - if (!g_option_context_parse (context, &argc, &argv, &error) || error != NULL) - { - /* an error occurred */ - g_application_command_line_printerr (cmdline, "%s\n", error->message); - g_error_free (error); - g_application_command_line_set_exit_status (cmdline, EXIT_FAILURE); - } - else if (do_register) - { - if (unit != NULL && *unit != '\0' && timeout >= 0) - { - /* register was called correctly */ - la_handler_service_register (LA_HANDLER_APPLICATION (application)->service, - unit, mode ? mode : "normal", (guint) timeout); - } - else - { - /* register was called incorrectly */ - g_application_command_line_printerr (cmdline, - "Invalid arguments. A unit must be " - "specified and the timeout must be " - "positive.\n"); - } - } - - /* clean up */ - g_free (argv); - g_strfreev (args); - g_option_context_free (context); - - g_free (mode); - g_free (unit); - - /* allow the application to stop */ - g_application_release (application); - - return EXIT_SUCCESS; -} - - - LAHandlerApplication * la_handler_application_new (LAHandlerService *service, GApplicationFlags flags) diff --git a/legacy-app-handler/main.c b/legacy-app-handler/main.c index a7a9d93..398ac04 100644 --- a/legacy-app-handler/main.c +++ b/legacy-app-handler/main.c @@ -21,6 +21,7 @@ #include #include +#include #include @@ -38,6 +39,177 @@ dlt_cleanup (void) +static gboolean +handle_command_line (int argc, + char **argv, + GDBusConnection *connection) +{ + GOptionContext *context = g_option_context_new (NULL); + LAHandler *legacy_app_handler; + gboolean do_register = FALSE; + gboolean do_deregister = FALSE; + GError *error = NULL; + gchar *unit = NULL; + gchar *log_message = NULL; + gchar *mode = NULL; + gint timeout = 0; + + GOptionEntry entries[] = { + {"deregister", 0, 0, G_OPTION_ARG_NONE, &do_deregister, NULL, NULL}, + {"register", 0, 0, G_OPTION_ARG_NONE, &do_register, NULL, NULL}, + {"unit", 0, 0, G_OPTION_ARG_STRING, &unit, NULL, NULL}, + {"timeout", 0, 0, G_OPTION_ARG_INT, &timeout, NULL, NULL}, + {"shutdown-mode", 0, 0, G_OPTION_ARG_STRING, &mode, NULL, NULL}, + {NULL}, + }; + + /* set up the option context */ + g_option_context_set_help_enabled (context, FALSE); + g_option_context_add_main_entries (context, entries, NULL); + + /* parse the arguments into argument data */ + if (!g_option_context_parse (context, &argc, &argv, &error) || error != NULL) + { + /* an error occurred */ + log_message = + g_strdup_printf ("Error occurred parsing arguments: %s\n", error->message); + DLT_LOG (la_handler_context, DLT_LOG_ERROR, DLT_STRING (log_message)); + + g_error_free (error); + g_free (log_message); + + return FALSE; + } + else if (do_register && !do_deregister) + { + if (unit == NULL || *unit == '\0' || timeout < 0) + { + /* register was called incorrectly */ + log_message = + g_strdup_printf ("Invalid arguments for --register. A unit must be specified" + " and the timeout must be positive."); + DLT_LOG (la_handler_context, DLT_LOG_ERROR, DLT_STRING (log_message)); + + g_free (log_message); + + return FALSE; + } + + /* get a legacy app handler interface */ + legacy_app_handler = + la_handler_proxy_new_sync (connection, G_DBUS_PROXY_FLAGS_NONE, + "org.genivi.LegacyAppHandler1", + "/org/genivi/LegacyAppHandler1", NULL, &error); + if (error != NULL) + { + /* failed to connect to the legacy app handler */ + log_message = + g_strdup_printf ("Error occurred connecting to legacy app handler " + "interface: %s", error->message); + DLT_LOG (la_handler_context, DLT_LOG_ERROR, DLT_STRING (log_message)); + + g_free (log_message); + g_error_free (error); + + return FALSE; + } + + /* call the legacy app handler's Register() method */ + la_handler_call_register_sync (legacy_app_handler, unit, + mode ? mode : "normal", (guint) timeout, NULL, + &error); + if (error != NULL) + { + /* failed to register the legacy app */ + log_message = g_strdup_printf ("Error occurred registering legacy app: %s", + error->message); + DLT_LOG (la_handler_context, DLT_LOG_ERROR, DLT_STRING (log_message)); + + g_object_unref (legacy_app_handler); + g_free (log_message); + g_error_free (error); + + return FALSE; + } + + g_object_unref (legacy_app_handler); + + return TRUE; + + } + else if (do_deregister && !do_register) + { + if (unit == NULL || *unit == '\0') + { + /* deregister was called incorrectly */ + log_message = + g_strdup_printf ("Invalid arguments for --deregister. A unit must be " + "specified."); + DLT_LOG (la_handler_context, DLT_LOG_ERROR, DLT_STRING (log_message)); + + g_free (log_message); + + return FALSE; + } + + /* get a legacy app handler interface */ + legacy_app_handler = + la_handler_proxy_new_sync (connection, G_DBUS_PROXY_FLAGS_NONE, + "org.genivi.LegacyAppHandler1", + "/org/genivi/LegacyAppHandler1", NULL, &error); + if (error != NULL) + { + log_message = + g_strdup_printf ("Error occurred connecting to legacy app handler " + "interface: %s", error->message); + DLT_LOG (la_handler_context, DLT_LOG_ERROR, DLT_STRING (log_message)); + + g_free (log_message); + g_error_free (error); + + return FALSE; + } + + /* call the legacy app handler's Deregister() method */ + la_handler_call_deregister_sync (legacy_app_handler, unit, NULL, &error); + if (error != NULL) + { + log_message = g_strdup_printf ("Error occurred deregistering legacy " + "app: %s", error->message); + DLT_LOG (la_handler_context, DLT_LOG_ERROR, DLT_STRING (log_message)); + + g_object_unref (legacy_app_handler); + g_free (log_message); + g_error_free (error); + + return FALSE; + } + + g_object_unref (legacy_app_handler); + + return TRUE; + } + else if (do_register && do_deregister) + { + log_message = + g_strdup_printf ("Invalid arguments. Please choose either --register or " + "--deregister."); + DLT_LOG (la_handler_context, DLT_LOG_ERROR, DLT_STRING (log_message)); + + g_free (log_message); + + return FALSE; + } + else + { + DLT_LOG (la_handler_context, DLT_LOG_ERROR, + DLT_STRING ("No arguments recognised")); + return FALSE; + } +} + + + int main (int argc, char **argv) @@ -82,48 +254,43 @@ main (int argc, return EXIT_FAILURE; } - /* instantiate the LegacyAppHandler service implementation */ - service = la_handler_service_new (connection); - if (!la_handler_service_start (service, &error)) - { - log_text = g_strdup_printf ("Failed to start the legacy app handler service: %s", - error->message); - DLT_LOG (la_handler_context, DLT_LOG_ERROR, DLT_STRING (log_text)); - - /* clean up */ - g_free (log_text); - g_error_free (error); - g_object_unref (service); - g_object_unref (connection); - - return EXIT_FAILURE; - } - - /* create and run the main application */ if (is_remote) { - /* an application with the flag G_APPLICATION_IS_SERVICE tries to be the primary - * instance of the application, and fails if another instance already exists. - * setting G_APPLICATION_IS_LAUNCHER indicates that it shouldn't try to be the - * primary instance */ - application = - la_handler_application_new (service, G_APPLICATION_HANDLES_COMMAND_LINE | - G_APPLICATION_IS_LAUNCHER); + if (!handle_command_line (argc, argv, connection)) + exit_status = EXIT_FAILURE; + else + exit_status = EXIT_SUCCESS; } else { - /* this application is meant to be the primary instance, so - * G_APPLICATION_IS_LAUNCHER is not set */ + /* instantiate the LegacyAppHandler service implementation */ + service = la_handler_service_new (connection); + if (!la_handler_service_start (service, &error)) + { + log_text = g_strdup_printf ("Failed to start the legacy app handler service: %s", + error->message); + DLT_LOG (la_handler_context, DLT_LOG_ERROR, DLT_STRING (log_text)); + + /* clean up */ + g_free (log_text); + g_error_free (error); + g_object_unref (service); + g_object_unref (connection); + + return EXIT_FAILURE; + } + + /* create and run the main application */ application = la_handler_application_new (service, G_APPLICATION_IS_SERVICE); - } - /* run the application */ - exit_status = g_application_run (G_APPLICATION (application), argc, argv); - g_object_unref (application); + exit_status = g_application_run (G_APPLICATION (application), argc, argv); + g_object_unref (application); + + /* release allocated objects */ + g_object_unref (service); + } - /* release allocated objects */ - g_object_unref (service); g_object_unref (connection); return exit_status; diff --git a/legacy-app-handler/systemd/Makefile.am b/legacy-app-handler/systemd/Makefile.am new file mode 100644 index 0000000..874d9e6 --- /dev/null +++ b/legacy-app-handler/systemd/Makefile.am @@ -0,0 +1,20 @@ +# vi:set ts=8 sw=8 noet ai nocindent: + +systemd_servicedir = $(libdir)/systemd/system + +systemd_service_in_files = \ + org.genivi.LegacyAppHandler1.service.in + +systemd_service_DATA = $(systmd_service_in_files:.service.in=.service) + +%.service: %.service.in + sed -e "s,\@libdir\@,$(libdir),g" \ + -e "s,\@BOOT_MANAGER_VERSION_API\@,$(BOOT_MANAGER_VERSION_API),g" < $< > $@ + +CLEANFILES = \ + $(systemd_service_DATA) + +EXTRA_DIST = \ + $(systemd_service_in_files) + + diff --git a/legacy-app-handler/systemd/org.genivi.LegacyAppHandler1.service.in b/legacy-app-handler/systemd/org.genivi.LegacyAppHandler1.service.in new file mode 100644 index 0000000..bc1f4b4 --- /dev/null +++ b/legacy-app-handler/systemd/org.genivi.LegacyAppHandler1.service.in @@ -0,0 +1,3 @@ +[Service] +BusName = org.genivi.LegacyAppHandler1.service +ExecStart = @libdir@/legacy-app-handler-@BOOT_MANAGER_VERSION_API@/legacy-app-handler