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