bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 1/3] console-client: add daemonizing support


From: Justus Winter
Subject: [PATCH 1/3] console-client: add daemonizing support
Date: Wed, 17 Jul 2013 13:09:04 +0200

This patch adds daemonizing support using libdaemon.

* console-client/console.c (daemonize): New variable.
(options): Add --daemonize argument.
(parse_opt): Handle --daemonize argument.
(daemon_error): New error(3) like macro.
(main): Daemonize.
---
 console-client/Makefile  |    2 +-
 console-client/console.c |  104 +++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 100 insertions(+), 6 deletions(-)

diff --git a/console-client/Makefile b/console-client/Makefile
index 69a7e37..0ad7a53 100644
--- a/console-client/Makefile
+++ b/console-client/Makefile
@@ -37,7 +37,7 @@ SRCS = $(CONSOLE_SRCS) \
 VPATH += $(srcdir)/xkb
 OBJS = $(addsuffix .o,$(basename $(notdir $(SRCS)))) kdioctlServer.o
 HURDLIBS = cons ports netfs fshelp iohelp ihash shouldbeinlibc
-LDLIBS = -ldl -lpthread
+LDLIBS = -ldl -lpthread -ldaemon
 module-dir = $(libdir)/hurd/console
 console-LDFLAGS = -Wl,-E
 
diff --git a/console-client/console.c b/console-client/console.c
index 7c9a880..7dd7a00 100644
--- a/console-client/console.c
+++ b/console-client/console.c
@@ -26,6 +26,7 @@
 #include <assert.h>
 
 #include <pthread.h>
+#include <libdaemon/daemon.h>
 
 #include <hurd/console.h>
 #include <hurd/cons.h>
@@ -61,6 +62,8 @@ static cons_t saved_cons;
    set.  */
 static char *console_node;
 
+/* If set, the client will daemonize.  */
+static int daemonize;
 
 /* Callbacks for input source drivers.  */
 
@@ -516,6 +519,8 @@ cons_vcons_set_mousecursor_status (vcons_t vcons, int 
status)
 }
 
 
+#define DAEMONIZE_KEY 0x80 /* !isascii (DAEMONIZE_KEY), so no short option.  */
+
 /* Console-specific options.  */
 static const struct argp_option
 options[] =
@@ -524,6 +529,7 @@ options[] =
     {"driver", 'd', "NAME", 0, "Add driver NAME to the console" },
     {"console-node", 'c', "FILE", OPTION_ARG_OPTIONAL,
      "Set a translator on the node FILE (default: " DEFAULT_CONSOLE_NODE ")" },
+    {"daemonize", DAEMONIZE_KEY, NULL, 0, "daemonize the console client"},
     {0}
   };
 
@@ -577,7 +583,11 @@ parse_opt (int key, char *arg, struct argp_state *state)
       if (!console_node)
        return ENOMEM;
       break;
-      
+
+    case DAEMONIZE_KEY:
+      daemonize = 1;
+      break;
+
     case ARGP_KEY_SUCCESS:
       if (!devcount)
        {
@@ -598,6 +608,28 @@ static const struct argp_child startup_children[] =
 static struct argp startup_argp = {options, parse_opt, 0,
                                   0, startup_children};
 
+#define daemon_error(status, errnum, format, args...)                   \
+  do                                                                    \
+    {                                                                   \
+      if (daemonize)                                                    \
+        {                                                               \
+          if (errnum)                                                   \
+            daemon_log (LOG_ERR, format ": %s", ##args,                 \
+                        strerror(errnum));                              \
+          else                                                          \
+            daemon_log (LOG_ERR, format, ##args);                       \
+          if (status)                                                   \
+            {                                                           \
+              /* Signal parent.  */                                     \
+              daemon_retval_send (status);                              \
+              return 0;                                                 \
+            }                                                           \
+        }                                                               \
+      else                                                              \
+        error (status, errnum, format, ##args);                         \
+    }                                                                   \
+  while (0);
+
 int
 main (int argc, char *argv[])
 {
@@ -609,9 +641,67 @@ main (int argc, char *argv[])
   /* Parse our command line.  This shouldn't ever return an error.  */
   argp_parse (&startup_argp, argc, argv, ARGP_IN_ORDER, 0, 0);
 
+  if (daemonize)
+    {
+      /* Reset signal handlers.  */
+      if (daemon_reset_sigs (-1) < 0)
+        error (1, errno, "Failed to reset all signal handlers");
+
+      /* Unblock signals.  */
+      if (daemon_unblock_sigs (-1) < 0)
+        error (1, errno, "Failed to unblock all signals");
+
+      /* Set indetification string for the daemon for both syslog and
+         PID file.  */
+      daemon_pid_file_ident = daemon_log_ident = \
+        daemon_ident_from_argv0 (argv[0]);
+
+      /* Check that the daemon is not run twice at the same time.  */
+      pid_t pid;
+      if ((pid = daemon_pid_file_is_running ()) >= 0)
+        error (1, errno, "Daemon already running on PID file %u", pid);
+
+      /* Prepare for return value passing from the initialization
+         procedure of the daemon process.  */
+      if (daemon_retval_init () < 0)
+        error (1, errno, "Failed to create pipe.");
+
+      /* Do the fork.  */
+      if ((pid = daemon_fork ()) < 0)
+        {
+          /* Exit on error.  */
+          daemon_retval_done ();
+          error (1, errno, "Failed to fork");
+        }
+      else if (pid)
+        {
+          /* The parent.  */
+          int ret;
+
+          /* Wait for 20 seconds for the return value passed from the
+             daemon process. .  */
+          if ((ret = daemon_retval_wait (20)) < 0)
+            error (1, errno,
+                   "Could not receive return value from daemon process");
+
+          return ret;
+        }
+      else
+        {
+          /* The daemon.  */
+          /* Close FDs.  */
+          if (daemon_close_all (-1) < 0)
+            daemon_error (1, errno, "Failed to close all file descriptors");
+
+          /* Create the PID file.  */
+          if (daemon_pid_file_create () < 0)
+            daemon_error (2, errno, "Could not create PID file");
+        }
+    }
+
   err = driver_start (&errname);
   if (err)
-    error (1, err, "Starting driver %s failed", errname);
+    daemon_error (1, err, "Starting driver %s failed", errname);
     
   pthread_mutex_init (&global_lock, NULL);
 
@@ -619,19 +709,23 @@ main (int argc, char *argv[])
   if (err)
     {
       driver_fini ();
-      error (1, err, "Console library initialization failed");
+      daemon_error (1, err, "Console library initialization failed");
     }
 
   err = timer_init ();
   if (err)
     {
       driver_fini ();
-      error (1, err, "Timer thread initialization failed");
+      daemon_error (1, err, "Timer thread initialization failed");
     }
 
   if (console_node)
     console_setup_node (console_node);
-  
+
+  if (daemonize)
+    /* Signal parent that all went well.  */
+    daemon_retval_send(0);
+
   cons_server_loop ();
 
   /* Never reached.  */
-- 
1.7.10.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]