summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Maw <jonathan.maw@codethink.co.uk>2012-06-26 15:44:00 +0100
committerJonathan Maw <jonathan.maw@codethink.co.uk>2012-06-29 11:21:50 +0100
commit4923d259d87b4b17d10eba73a9cee3a1fe80dda2 (patch)
treef2044d37525e82ec316b7833ab5acf4dc931813d
parent084acbce717610fd50d9b706996af6c11712f40a (diff)
downloadnode-startup-controller-4923d259d87b4b17d10eba73a9cee3a1fe80dda2.tar.gz
Add --register command-line option to LegacyAppHandler
When legacy-app-handler is called without arguments, it starts as a service, and as the primary instance of the LegacyAppHandler GApplication. When legacy-app-handler is called with arguments, it is started as a remote instance of the LegacyAppHandler GApplication, which passes its command-line arguments to the primary instance. On receiving command-line arguments from a remote instance, the Primary instance will parse those arguments, expecting a command like the following: legacy-app-handler --register --unit="foo" --timeout=120 \ --shutdown-mode="normal" Timeout and shutdown-mode are optional, and if omitted will default to 0, and "normal", respectively. Because interaction with the Node State Manager is not yet implemented, the Legacy App Handler will print the arguments to DLT, instead of registering the app as a shutdown consumer.
-rw-r--r--legacy-app-handler/la-handler-application.c137
-rw-r--r--legacy-app-handler/la-handler-application.h5
-rw-r--r--legacy-app-handler/main.c53
3 files changed, 177 insertions, 18 deletions
diff --git a/legacy-app-handler/la-handler-application.c b/legacy-app-handler/la-handler-application.c
index 0ce2b78..7295bcb 100644
--- a/legacy-app-handler/la-handler-application.c
+++ b/legacy-app-handler/la-handler-application.c
@@ -11,9 +11,15 @@
#include <config.h>
#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
#include <glib-object.h>
#include <gio/gio.h>
+#include <dlt/dlt.h>
+
#include <common/watchdog-client.h>
#include <legacy-app-handler/la-handler-dbus.h>
@@ -22,6 +28,10 @@
+DLT_IMPORT_CONTEXT (la_handler_context);
+
+
+
/* property identifiers */
enum
{
@@ -31,16 +41,18 @@ enum
-static void la_handler_application_finalize (GObject *object);
-static void la_handler_application_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec);
-static void la_handler_application_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec);
-static void la_handler_application_startup (GApplication *application);
+static void la_handler_application_finalize (GObject *object);
+static void la_handler_application_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void la_handler_application_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void la_handler_application_startup (GApplication *application);
+static int la_handler_application_command_line (GApplication *application,
+ GApplicationCommandLine *cmdline);
@@ -80,6 +92,7 @@ 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,
@@ -107,7 +120,8 @@ la_handler_application_finalize (GObject *object)
LAHandlerApplication *application = LA_HANDLER_APPLICATION (object);
/* release the watchdog client */
- g_object_unref (application->watchdog_client);
+ if (application->watchdog_client != NULL)
+ g_object_unref (application->watchdog_client);
/* release the Legacy App Handler service implementation */
if (application->service != NULL)
@@ -165,18 +179,115 @@ la_handler_application_startup (GApplication *app)
{
LAHandlerApplication *application = LA_HANDLER_APPLICATION (app);
+ /* chain up to the parent class */
+ (*G_APPLICATION_CLASS (la_handler_application_parent_class)->startup) (app);
+
/* update systemd's watchdog timestamp every 120 seconds */
application->watchdog_client = watchdog_client_new (120);
+
+ /* the Legacy Application Handler should keep running until it is shut down by the Node
+ * State Manager. */
+ g_application_hold (app);
+}
+
+
+
+static int
+la_handler_application_command_line (GApplication *application,
+ GApplicationCommandLine *cmdline)
+{
+ GOptionContext *context;
+ gboolean do_register;
+ GError *error;
+ gchar **args;
+ gchar **argv;
+ gchar *message;
+ gchar *mode = NULL;
+ gchar *unit = NULL;
+ gint argc;
+ gint timeout;
+ 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))
+ {
+ /* 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 */
+ message =
+ g_strdup_printf ("Register application \"%s\" with mode \"%s\"and "
+ "timeout %dms",
+ unit,
+ (mode != NULL) ? mode : "normal",
+ timeout);
+ DLT_LOG (la_handler_context, DLT_LOG_INFO, DLT_STRING (message));
+ g_free (message);
+ }
+ 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)
+la_handler_application_new (LAHandlerService *service,
+ GApplicationFlags flags)
{
return g_object_new (LA_HANDLER_TYPE_APPLICATION,
"application-id", "org.genivi.LegacyAppHandler1",
- "flags", G_APPLICATION_IS_SERVICE,
+ "flags", flags,
"la-handler-service", service,
NULL);
}
diff --git a/legacy-app-handler/la-handler-application.h b/legacy-app-handler/la-handler-application.h
index e77cfa6..57160e2 100644
--- a/legacy-app-handler/la-handler-application.h
+++ b/legacy-app-handler/la-handler-application.h
@@ -24,9 +24,10 @@ G_BEGIN_DECLS
typedef struct _LAHandlerApplicationClass LAHandlerApplicationClass;
typedef struct _LAHandlerApplication LAHandlerApplication;
-GType la_handler_application_get_type (void) G_GNUC_CONST;
+GType la_handler_application_get_type (void) G_GNUC_CONST;
-LAHandlerApplication *la_handler_application_new (LAHandlerService *service) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+LAHandlerApplication *la_handler_application_new (LAHandlerService *service,
+ GApplicationFlags flags) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
G_END_DECLS
diff --git a/legacy-app-handler/main.c b/legacy-app-handler/main.c
index df81e05..f19dbfd 100644
--- a/legacy-app-handler/main.c
+++ b/legacy-app-handler/main.c
@@ -18,11 +18,26 @@
#include <glib.h>
#include <gio/gio.h>
+#include <dlt/dlt.h>
+
#include <legacy-app-handler/la-handler-application.h>
#include <legacy-app-handler/la-handler-service.h>
+DLT_DECLARE_CONTEXT (la_handler_context);
+
+
+
+static void
+dlt_cleanup (void)
+{
+ DLT_UNREGISTER_CONTEXT (la_handler_context);
+ DLT_UNREGISTER_APP ();
+}
+
+
+
int
main (int argc,
char **argv)
@@ -30,8 +45,24 @@ main (int argc,
LAHandlerApplication *application;
LAHandlerService *service;
GDBusConnection *connection;
+ gboolean is_remote;
GError *error = NULL;
- gint exit_status = EXIT_SUCCESS;
+ int exit_status;
+
+ /* check if this program execution is meant as a remote application.
+ * if it is a remote application, then it will be called with command-line arguments. */
+ is_remote = (argc > 1) ? TRUE : FALSE;
+
+ /* register the application and context in DLT */
+ if (!is_remote)
+ {
+ DLT_REGISTER_APP ("BMGR", "GENIVI Boot Manager");
+ DLT_REGISTER_CONTEXT (la_handler_context, "LAH",
+ "Context of the legacy application handler that hooks legacy "
+ "applications up with the shutdown concept of the Node State "
+ "Manager");
+ atexit (dlt_cleanup);
+ }
/* initialize the GType type system */
g_type_init ();
@@ -63,8 +94,24 @@ main (int argc,
}
/* create and run the main application */
- application = la_handler_application_new (service);
- exit_status = g_application_run (G_APPLICATION (application), 0, NULL);
+ 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);
+ }
+ else
+ {
+ /* this application is meant to be the primary instance, so
+ * G_APPLICATION_IS_LAUNCHER is not set */
+ application =
+ la_handler_application_new (service, G_APPLICATION_IS_SERVICE);
+ }
+ exit_status = g_application_run (G_APPLICATION (application), argc, argv);
g_object_unref (application);
/* release allocated objects */