--- 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 #include #include +#include +#include +#include +#include +#include // 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); }