Blob Blame History Raw
--- xtide-2.14/xttpd.cc.pidfile	2014-10-12 04:42:10.000000000 +0900
+++ xtide-2.14/xttpd.cc	2015-12-30 21:05:16.087233767 +0900
@@ -34,6 +34,11 @@ using namespace libxtide;
 #include <netdb.h>
 #include <pwd.h>
 #include <grp.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <unistd.h>
 
 
 // These browsers nowadays can get pretty verbose.
@@ -44,6 +49,11 @@ static const size_t bufsize (10000);
 static Dstr webmaster;
 static ZoneIndex zoneIndex;
 static bool zoneinfoIsNotHorriblyObsolete;
+static int processTermReason = 0;
+
+// Pid file name
+#define PID_FILE_DIR "/var/run/xttpd"
+#define PID_FILE_NAME PID_FILE_DIR "/xttpd.pid"
 
 
 namespace TimeControl {
@@ -1153,6 +1163,89 @@ static void dontBeRoot() {
   }
 }
 
+static void createPidFileDirectory(void) {
+  struct stat st;
+  mode_t dirMode = S_IRWXU | S_IRGRP | S_IXGRP;
+
+  if (stat(PID_FILE_DIR, &st) != 0) {
+    int errnum = errno;
+    if (errnum != ENOENT) {
+      Global::xperror("stat");
+      exit (-1);
+    }
+
+    if (mkdir(PID_FILE_DIR, dirMode) < 0) {
+      Global::xperror("mkdir");
+      exit (-1);
+    }
+
+    if (stat(PID_FILE_DIR, &st) != 0) {
+      Global::xperror("stat");
+      exit (-1);
+    }
+  }
+
+  // Make it sure that PID_FILE_DIR is a directory
+   // (not a symlink or so)
+  if (!S_ISDIR(st.st_mode)) {
+    Dstr msg (PID_FILE_DIR " is not a directory");
+    Global::log (msg, LOG_ERR);
+    exit (-1);
+  }
+
+  // Again chmod
+  if (chmod(PID_FILE_DIR, dirMode) < 0) {
+    Global::xperror("chmod");
+    exit (-1);
+  }
+
+  group *gr = getgrnam (xttpd_group);
+  if (!gr) {
+    Global::xperror ("getgrnam");
+    exit (-1);
+  }
+  passwd *nb = getpwnam (xttpd_user);
+  if (!nb) {
+    Global::xperror ("getpwnam");
+    exit(-1);
+  }
+
+  if (chown(PID_FILE_DIR, nb->pw_uid, gr->gr_gid) < 0) {
+    Global::xperror ("chown");
+    exit(-1);
+  }
+
+}
+
+static void writePidFile(pid_t pid) {
+  FILE *pidFd = fopen(PID_FILE_NAME, "w");
+  if (!pidFd) {
+    Global::xperror("fopen");
+    exit (-1);
+  }
+
+  if (fprintf(pidFd, "%d", (int)pid) < 0) {
+    Global::xperror ("fprintf");
+    exit (-1);
+  }
+
+  fclose(pidFd);
+}
+
+static void handlerSigterm(int sig) {
+  processTermReason = sig;
+}
+
+static void initSignalHander(void) {
+  struct sigaction sigact;
+  memset(&sigact, 0, sizeof sigact);
+
+  sigemptyset(&sigact.sa_mask);
+  sigact.sa_flags |= SA_RESTART;
+  sigact.sa_handler = handlerSigterm;
+
+  sigaction(SIGTERM, &sigact, NULL);
+}
 
 int main (int argc, char **argv) {
 
@@ -1181,7 +1274,13 @@ int main (int argc, char **argv) {
       portNumberEvade = parseAddress (portnum, addr, argv[1]);
     setupSocket (portnum, addr, listenSocket);
   }
+  // Create pid directory before dropping priviledge
+  createPidFileDirectory();
   dontBeRoot();
+  writePidFile(getpid());
+
+  // Initialize signal handler
+  initSignalHander();
 
   // An unfortunate consequence of needing to drop root ASAP is that
   // failure to bind the port prevents xttpd -v from working.
@@ -1212,7 +1311,7 @@ int main (int argc, char **argv) {
   FD_ZERO (&rdset);
   FD_SET (listenSocket, &rdset);
   sockaddr addr;
-  while (true) {
+  while (!processTermReason) {
     fd_set trdset, twrset, texset;
     trdset = rdset;
     // I seem to remember that some platforms barf if you provide
@@ -1235,6 +1334,7 @@ int main (int argc, char **argv) {
     while (waitpid (-1, (int*)NULL, WNOHANG|WUNTRACED) > 0);
   }
 
+  unlink(PID_FILE_NAME);
   exit (0);
 }