summaryrefslogtreecommitdiff
path: root/src/daemon/plugins/plugind/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/daemon/plugins/plugind/main.c')
-rw-r--r--src/daemon/plugins/plugind/main.c191
1 files changed, 191 insertions, 0 deletions
diff --git a/src/daemon/plugins/plugind/main.c b/src/daemon/plugins/plugind/main.c
new file mode 100644
index 0000000..2c0bfd7
--- /dev/null
+++ b/src/daemon/plugins/plugind/main.c
@@ -0,0 +1,191 @@
+/* vi: set et sw=4 ts=4 cino=t0,(0: */
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of gsignond
+ *
+ * Copyright (C) 2013 Intel Corporation.
+ *
+ * Contact: Imran Zaman <imran.zaman@intel.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <config.h>
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <stdio.h>
+#include <glib-unix.h>
+#include <glib.h>
+#include <gio/gio.h>
+#include <sys/prctl.h>
+
+#include "gsignond/gsignond-log.h"
+#include "daemon/dbus/gsignond-dbus.h"
+#include "gsignond-plugin-daemon.h"
+
+static GSignondPluginDaemon *_daemon = NULL;
+static guint _sig_source_id[3];
+
+static void
+_on_daemon_closed (gpointer data, GObject *server)
+{
+ _daemon = NULL;
+ DBG ("Daemon closed");
+ if (data) g_main_loop_quit ((GMainLoop *)data);
+}
+
+static gboolean
+_handle_quit_signal (gpointer user_data)
+{
+ GMainLoop *ml = (GMainLoop *) user_data;
+
+ g_return_val_if_fail (ml != NULL, FALSE);
+ DBG ("Received quit signal");
+ if (ml) g_main_loop_quit (ml);
+
+ return FALSE;
+}
+
+static void
+_install_sighandlers (GMainLoop *main_loop)
+{
+ GSource *source = NULL;
+ GMainContext *ctx = g_main_loop_get_context (main_loop);
+
+ source = g_unix_signal_source_new (SIGTERM);
+ g_source_set_callback (source,
+ _handle_quit_signal,
+ main_loop,
+ NULL);
+ _sig_source_id[0] = g_source_attach (source, ctx);
+
+ source = g_unix_signal_source_new (SIGINT);
+ g_source_set_callback (source,
+ _handle_quit_signal,
+ main_loop,
+ NULL);
+ _sig_source_id[1] = g_source_attach (source, ctx);
+
+ source = g_unix_signal_source_new (SIGHUP);
+ g_source_set_callback (source,
+ _handle_quit_signal,
+ main_loop,
+ NULL);
+ _sig_source_id[2] = g_source_attach (source, ctx);
+
+ if (prctl(PR_SET_PDEATHSIG, SIGHUP))
+ WARN ("failed to set parent death signal");
+}
+
+int main (int argc, char **argv)
+{
+ GError *error = NULL;
+ GMainLoop *main_loop = NULL;
+ GOptionContext *opt_context = NULL;
+ gchar **plugin_args = NULL;
+ gint up_signal = -1;
+ gint in_fd = 0, out_fd = 1;
+ GOptionEntry opt_entries[] = {
+ {G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &plugin_args,
+ "Plugin Args", NULL},
+ {NULL}
+ };
+
+ /* Duplicates stdin,stdout,stderr descriptors and point the descriptors
+ * to /dev/null to avoid anyone writing to descriptors before initial
+ * "plugind-is-ready" notification is sent to gsignond
+ * */
+ in_fd = dup(0);
+ if (in_fd == -1) {
+ WARN ("Failed to dup stdin : %s(%d)", strerror(errno), errno);
+ in_fd = 0;
+ }
+ if (!freopen("/dev/null", "r+", stdin)) {
+ WARN ("Unable to redirect stdin to /dev/null");
+ }
+
+ out_fd = dup(1);
+ if (out_fd == -1) {
+ WARN ("Failed to dup stdout : %s(%d)", strerror(errno), errno);
+ out_fd = 1;
+ }
+
+ /* Reattach stderr to stdout */
+ dup2 (2, 1);
+
+#if !GLIB_CHECK_VERSION (2, 36, 0)
+ g_type_init ();
+#endif
+
+ opt_context = g_option_context_new ("<plugin_path> <plugin_name>");
+ g_option_context_set_summary (opt_context, "gSSO helper plugin daemon");
+ g_option_context_add_main_entries (opt_context, opt_entries, NULL);
+ g_option_context_set_ignore_unknown_options (opt_context, TRUE);
+ g_option_context_parse (opt_context, &argc, &argv, &error);
+ g_option_context_free (opt_context);
+ if (error) {
+ WARN ("Error in arguments parsing: %s", error->message);
+ g_error_free (error);
+ }
+ if (!plugin_args || !plugin_args[0] || !plugin_args[1]) {
+ WARN ("plugin path or plugin type missing");
+ if (write (out_fd, "0", sizeof(char)) == -1)
+ WARN ("Unable to write down notification to stdout");
+ if (in_fd != 0) close (in_fd);
+ if (out_fd != 1) close (out_fd);
+ if (plugin_args) g_strfreev(plugin_args);
+ return -1;
+ }
+
+ _daemon = gsignond_plugin_daemon_new (plugin_args[0], plugin_args[1], in_fd,
+ out_fd);
+ g_strfreev(plugin_args);
+ if (_daemon == NULL) {
+ if (write (out_fd, "0", sizeof(char)) == -1)
+ WARN ("Unable to write down notification to stdout");
+ if (in_fd != 0) close (in_fd);
+ if (out_fd != 1) close (out_fd);
+ return -1;
+ }
+
+ main_loop = g_main_loop_new (NULL, FALSE);
+ g_object_weak_ref (G_OBJECT (_daemon), _on_daemon_closed, main_loop);
+ _install_sighandlers (main_loop);
+
+ /* Notification for gsignond that plugind is up and ready */
+ up_signal = write (out_fd, "1", sizeof(char));
+
+ if (up_signal == -1) {
+ g_main_loop_unref (main_loop);
+ g_object_unref (_daemon);
+ return -1;
+ }
+
+ DBG ("Entering main event loop");
+
+ g_main_loop_run (main_loop);
+
+ if(_daemon) {
+ g_object_unref (_daemon);
+ }
+
+ if (main_loop) {
+ g_main_loop_unref (main_loop);
+ }
+
+ return 0;
+}