about summary refs log tree commit diff
diff options
context:
space:
mode:
authorHeikki Kallasjoki <fis@zem.fi>2018-11-30 15:51:05 +0000
committerHeikki Kallasjoki <fis@zem.fi>2018-11-30 15:51:05 +0000
commit2c6ca9942bcecf062010c7c5e3c35e30d91f7434 (patch)
tree2093abc4dd5359b22c20b46799319c29271377b8
parent69e51e6eec450a9e0a896d93ccdb1a92abf4ff85 (diff)
downloadnano-exporter-2c6ca9942bcecf062010c7c5e3c35e30d91f7434.tar.gz
nano-exporter-2c6ca9942bcecf062010c7c5e3c35e30d91f7434.tar.xz
nano-exporter-2c6ca9942bcecf062010c7c5e3c35e30d91f7434.zip
Daemonize to background by default.
-rw-r--r--README.md1
-rw-r--r--main.c67
2 files changed, 65 insertions, 3 deletions
diff --git a/README.md b/README.md
index 52f863d..79ef13a 100644
--- a/README.md
+++ b/README.md
@@ -65,6 +65,7 @@ Reference](#collector-reference) section.
 
 | Flag | Description |
 | ---- | ----------- |
+| `--foreground` | Don't daemonize, but remain on the foreground instead. |
 | `--port=X` | Listen on port *X* instead of the default port (9100). |
 
 ## Collector Reference
diff --git a/main.c b/main.c
index 08b7dab..43acbcb 100644
--- a/main.c
+++ b/main.c
@@ -3,7 +3,11 @@
 #include <stdbool.h>
 #include <stddef.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
 
 #include "collector.h"
 #include "scrape.h"
@@ -30,6 +34,12 @@ enum tristate { flag_off = -1, flag_undef = 0, flag_on = 1 };
 
 struct config {
   const char *port;
+  bool daemonize;
+};
+
+const struct config default_config = {
+  .port = "9100",
+  .daemonize = true,
 };
 
 struct handler_ctx {
@@ -43,12 +53,11 @@ struct handler_ctx {
 
 static bool parse_args(int argc, char *argv[], struct config *cfg, struct handler_ctx *ctx);
 static bool initialize(struct handler_ctx *ctx, int max_args);
+static bool daemonize(void);
 static void handler(scrape_req *req, void *ctx_ptr);
 
 int main(int argc, char *argv[]) {
-  struct config cfg = {
-    .port = "9100",
-  };
+  struct config cfg = default_config;
   struct handler_ctx ctx;
 
   if (!parse_args(argc, argv, &cfg, &ctx))
@@ -60,6 +69,10 @@ int main(int argc, char *argv[]) {
   if (!server)
     return 1;
 
+  if (cfg.daemonize)
+    if (!daemonize())
+      return 1;
+
   scrape_serve(server, handler, &ctx);
   scrape_close(server);
 
@@ -105,6 +118,9 @@ static bool parse_args(int argc, char *argv[], struct config *cfg, struct handle
     if (strncmp(argv[arg], "--port=", 7) == 0) {
       cfg->port = &argv[arg][7];
       goto next_arg;
+    } else if (strcmp(argv[arg], "--foreground") == 0) {
+      cfg->daemonize = false;
+      goto next_arg;
     }
 
     fprintf(stderr, "unknown argument: %s\n", argv[arg]);
@@ -142,6 +158,51 @@ static bool initialize(struct handler_ctx *ctx, int max_args) {
   return true;
 }
 
+static bool daemonize(void) {
+  pid_t pid;
+
+  pid = fork();
+  if (pid == -1) {
+    perror("fork");
+    return false;
+  }
+
+  if (pid > 0) {
+    // in the parent, verify the intermediate process exits successfully
+    int status;
+    if (waitpid(pid, &status, 0) == -1) {
+      perror("waitpid(daemon)");
+      exit(1);
+    }
+    if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+      fprintf(stderr, "daemonized process exited unexpectedly: %x\n", status);
+      exit(1);
+    }
+    exit(0);
+  }
+
+  // in the intermediate process, prepare for daemon life and fork again
+
+  if (setsid() == -1) {
+    perror("setsid");
+    exit(1);
+  }
+
+  close(0);
+  close(1);
+  close(2);
+
+  pid = fork();
+  if (pid == -1)
+    exit(2);
+  else if (pid > 0)
+    exit(0);  // lets the parent know all is well
+
+  // in the grandchild, continue execution
+
+  return true;
+}
+
 static void handler(scrape_req *req, void *ctx_ptr) {
   struct handler_ctx *ctx = ctx_ptr;