aboutsummaryrefslogtreecommitdiffstats
path: root/src/daemonise.c
diff options
context:
space:
mode:
authorMattias Andrée <maandree@member.fsf.org>2016-01-01 23:19:03 +0100
committerMattias Andrée <maandree@member.fsf.org>2016-01-01 23:19:03 +0100
commit6bafe448eca660a25ea4718ef8291f9ade5b773b (patch)
tree1d9b9a8ca3b5d88200c22775059f6220c61fea56 /src/daemonise.c
parenttypo (diff)
downloadsat-6bafe448eca660a25ea4718ef8291f9ade5b773b.tar.gz
sat-6bafe448eca660a25ea4718ef8291f9ade5b773b.tar.bz2
sat-6bafe448eca660a25ea4718ef8291f9ade5b773b.tar.xz
remove unused stuff from daemonise
Signed-off-by: Mattias Andrée <maandree@member.fsf.org>
Diffstat (limited to 'src/daemonise.c')
-rw-r--r--src/daemonise.c406
1 files changed, 162 insertions, 244 deletions
diff --git a/src/daemonise.c b/src/daemonise.c
index 822e0ed..be7e33e 100644
--- a/src/daemonise.c
+++ b/src/daemonise.c
@@ -19,7 +19,10 @@
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
- * This file is copied from <http://github.com/maandree/slibc>.
+ * This file is copied from <http://github.com/maandree/slibc>,
+ * but with unused stuff removed. It has also been slightly modified
+ * and changed code style (these "slight" modifications do not change
+ * the behaviour.)
*/
#define _POSIX_C_SOURCE 200809L
#include "daemonise.h"
@@ -36,6 +39,9 @@
#include <sys/resource.h>
+#define t(...) do { if (__VA_ARGS__) goto fail; } while (0)
+#define S(...) (saved_errno = errno, __VA_ARGS__, errno = saved_errno)
+
/**
* The process's environment variables.
@@ -58,31 +64,28 @@ static char* __pidfile = NULL;
*
* @throws Any error specified for dup(3).
*/
-static int dup_at_least_3(int old)
+static int
+dup_at_least_3(int old)
{
- int intermediary[3];
- int i = 0, saved_errno;
-
- do
- {
- if (old = dup(old), old == -1)
- goto fail;
- assert(i < 3);
- if (i >= 3)
- abort();
- intermediary[i++] = old;
- }
- while (old < 3);
- i--;
-
- fail:
- saved_errno = errno;
- while (i--)
- close(intermediary[i]);
- errno = saved_errno;
- return old;
-}
+ int intermediary[3];
+ int i = 0, saved_errno;
+
+ do {
+ t (old = dup(old), old == -1);
+ assert(i < 3);
+ if (i >= 3)
+ abort();
+ intermediary[i++] = old;
+ } while (old < 3);
+ i--;
+fail:
+ saved_errno = errno;
+ while (i--)
+ close(intermediary[i]);
+ errno = saved_errno;
+ return old;
+}
/**
@@ -154,39 +157,15 @@ static int dup_at_least_3(int old)
*
* @param name The name of the daemon. Use a hardcoded value,
* not the process name. Must not be `NULL`.
- * @param flags Flags to modify the behaviour of the function.
- * A bitwise OR combination of the constants:
- * - `DAEMONISE_NO_CLOSE`
- * - `DAEMONISE_NO_SIG_DFL`
- * - `DAEMONISE_KEEP_SIGMASK`
- * - `DAEMONISE_KEEP_ENVIRON`
- * - `DAEMONISE_KEEP_UMASK`
- * - `DAEMONISE_NO_PID_FILE`
- * - `DAEMONISE_KEEP_STDERR`
- * - `DAEMONISE_CLOSE_STDERR`
- * - `DAEMONISE_KEEP_STDIN`
- * - `DAEMONISE_KEEP_STDOUT`
- * - `DAEMONISE_KEEP_FDS`
- * - `DAEMONISE_NEW_PID`
- * @param ... Enabled if `DAEMONISE_KEEP_FDS` is used,
- * do not add anything if `DAEMONISE_KEEP_FDS`
- * is unused. This is a `-1`-terminated list
- * of file descritors to keep open. 0, 1, and 2
- * are implied by `DAEMONISE_KEEP_STDIN`,
- * `DAEMONISE_KEEP_STDOUT`, and `DAEMONISE_KEEP_STDERR`,
- * respectively. All arguments are of type `int`.
+ * @param ... This is a `-1`-terminated list
+ * of file descritors to keep open.
+ * All arguments are of type `int`.
* @return Zero on success, -1 on error.
*
* @throws EEXIST The PID file already exists on the system.
* Unless your daemon supervisor removs old
* PID files, this could mean that the daemon
* has exited without removing the PID file.
- * @throws EINVAL `flags` contains an unsupported bit, both
- * `DAEMONISE_KEEP_STDERR` and `DAEMONISE_CLOSE_STDERR`
- * are set, both `DAEMONISE_NO_PID_FILE` and
- * `DAEMONISE_NEW_PID`, or both `DAEMONISE_CLOSE_STDERR`
- * and `DAEMONISE_KEEP_FDS` are set whilst `2` is
- * in the list of file descriptor not to close.
* @throws Any error specified for signal(3).
* @throws Any error specified for sigemptyset(3).
* @throws Any error specified for sigprocmask(3).
@@ -201,197 +180,138 @@ static int dup_at_least_3(int old)
*
* @since Always.
*/
-int daemonise(const char* name, int flags, ...)
+int daemonise(const char* name, ...)
{
-#define t(...) do { if (__VA_ARGS__) goto fail; } while (0)
-
- struct rlimit rlimit;
- int pipe_rw[2] = { -1, -1 };
- sigset_t set;
- char** r;
- char** w;
- char* run;
- int i, closeerr, fd = -1;
- char* keep = NULL;
- int keepmax = 0;
- pid_t pid;
- va_list args;
- int saved_errno;
-
-
- /* Validate flags. */
- if (flags & (int)~(2048L * 2 - 1))
- return errno = EINVAL, -1;
- if ((flags & DAEMONISE_KEEP_STDERR) && (flags & DAEMONISE_CLOSE_STDERR))
- return errno = EINVAL, -1;
- if ((flags & DAEMONISE_NO_PID_FILE) && (flags & DAEMONISE_NEW_PID))
- return errno = EINVAL, -1;
-
-
- /* Find out which file descriptors not too close. */
- if (flags & DAEMONISE_KEEP_FDS)
- {
- va_start(args, flags);
- while ((fd = va_arg(args, int)) >= 0)
- if ((fd > 2) && (keepmax < fd))
- keepmax = fd;
- fd = -1;
- va_end(args);
- keep = calloc((size_t)keepmax + 1, sizeof(char));
- t (keep == NULL);
- va_start(args, flags);
- while ((fd = va_arg(args, int)) >= 0)
- switch (fd)
- {
- case 0: flags |= DAEMONISE_KEEP_STDIN; break;
- case 1: flags |= DAEMONISE_KEEP_STDOUT; break;
- case 2: flags |= DAEMONISE_KEEP_STDERR;
- if (flags & DAEMONISE_CLOSE_STDERR)
- return free(keep), errno = EINVAL, -1;
- break;
- default:
- keep[fd] = 1;
- break;
- }
- fd = -1;
- va_end(args);
- }
- /* We assume that the maximum file descriptor is not extremely large.
- * We also assume the number of file descriptors too keep is very small,
- * but this does not affect us. */
-
- /* Close all files except stdin, stdout, and stderr. */
- if ((flags & DAEMONISE_NO_CLOSE) == 0)
- {
- if (getrlimit(RLIMIT_NOFILE, &rlimit))
- rlimit.rlim_cur = 4 << 10;
- for (i = 3; (rlim_t)i < rlimit.rlim_cur; i++)
- /* File descriptors with numbers above and including
- * `rlimit.rlim_cur` cannot be created. They cause EBADF. */
- if ((i > keepmax) || (keep[i] == 0))
- close(i);
- }
- free(keep), keep = NULL;
-
- /* Reset all signal handlers. */
- if ((flags & DAEMONISE_NO_SIG_DFL) == 0)
- for (i = 1; i < _NSIG; i++)
- if (signal(i, SIG_DFL) == SIG_ERR)
- t (errno != EINVAL);
-
- /* Set signal mask. */
- if ((flags & DAEMONISE_KEEP_SIGMASK) == 0)
- {
- t (sigemptyset(&set));
- t (sigprocmask(SIG_SETMASK, &set, NULL));
- }
-
- /* Remove malformatted environment entires. */
- if (((flags & DAEMONISE_KEEP_ENVIRON) == 0) && (environ != NULL))
- {
- for (r = w = environ; *r; r++)
- if (strchr(*r, '=')) /* It happens that this is not the case! (Thank you PAM!) */
- *w++ = *r;
- *w = NULL;
- }
-
- /* Zero umask. */
- if ((flags & DAEMONISE_KEEP_UMASK) == 0)
- umask(0);
-
- /* Change current working directory to '/'. */
- t (chdir("/"));
-
- /* Create a channel for letting the original process know when to exit. */
- if (pipe(pipe_rw))
- t ((pipe_rw[0] = pipe_rw[1] = -1));
- t (fd = dup_at_least_3(pipe_rw[0]), fd == -1);
- close(pipe_rw[0]);
- pipe_rw[0] = fd;
- t (fd = dup_at_least_3(pipe_rw[1]), fd == -1);
- close(pipe_rw[1]);
- pipe_rw[1] = fd;
-
- /* Become a background process. */
- t (pid = fork(), pid == -1);
- close(pipe_rw[!!pid]), pipe_rw[!!pid] = 1;
- if (pid)
- exit(read(pipe_rw[0], &fd, (size_t)1) <= 0);
-
- /* Temporarily become session leader. */
- t (setsid() == -1);
+ struct rlimit rlimit;
+ int pipe_rw[2] = { -1, -1 };
+ sigset_t set;
+ char** r;
+ char** w;
+ char* run;
+ int i, closeerr, fd = -1;
+ char* keep = NULL;
+ int keepmax = 0;
+ pid_t pid;
+ va_list args;
+ int saved_errno;
+
+ /* Find out which file descriptors not too close. */
+ va_start(args, name);
+ while ((fd = va_arg(args, int)) >= 0)
+ keepmax = fd;
+ fd = -1;
+ va_end(args);
+ keep = calloc((size_t)keepmax + 1, sizeof(char));
+ t (keep == NULL);
+ va_start(args, name);
+ while ((fd = va_arg(args, int)) >= 0)
+ keep[fd] = 1;
+ fd = -1;
+ va_end(args);
+ /* We assume that the maximum file descriptor is not extremely large.
+ * We also assume the number of file descriptors too keep is very small,
+ * but this does not affect us. */
- /* Fork again. */
- t (pid = fork(), pid == -1);
- if (pid > 0)
- exit(0);
+ /* Close all files except stdin, stdout, and stderr. */
+ if (getrlimit(RLIMIT_NOFILE, &rlimit))
+ rlimit.rlim_cur = 4 << 10;
+ for (i = 3; (rlim_t)i < rlimit.rlim_cur; i++)
+ /* File descriptors with numbers above and including
+ * `rlimit.rlim_cur` cannot be created. They cause EBADF. */
+ if ((i > keepmax) || (keep[i] == 0))
+ close(i);
+ free(keep), keep = NULL;
+
+ /* Reset all signal handlers. */
+ for (i = 1; i < _NSIG; i++)
+ if (signal(i, SIG_DFL) == SIG_ERR)
+ t (errno != EINVAL);
+
+ /* Set signal mask. */
+ t (sigemptyset(&set));
+ t (sigprocmask(SIG_SETMASK, &set, NULL));
+
+ /* Remove malformatted environment entires. */
+ if (environ) {
+ for (r = w = environ; *r; r++)
+ if (strchr(*r, '=')) /* It happens that this is not the case! (Thank you PAM!) */
+ *w++ = *r;
+ *w = NULL;
+ }
+
+ /* Zero umask. */
+ umask(0);
+
+ /* Change current working directory to '/'. */
+ t (chdir("/"));
+
+ /* Create a channel for letting the original process know when to exit. */
+ if (pipe(pipe_rw))
+ t ((pipe_rw[0] = pipe_rw[1] = -1));
+ t (fd = dup_at_least_3(pipe_rw[0]), fd == -1);
+ close(pipe_rw[0]);
+ pipe_rw[0] = fd;
+ t (fd = dup_at_least_3(pipe_rw[1]), fd == -1);
+ close(pipe_rw[1]);
+ pipe_rw[1] = fd;
- /* Create PID file. */
- if (flags & DAEMONISE_NO_PID_FILE)
- goto no_pid_file;
- run = getenv("XDG_RUNTIME_DIR");
- if (run && *run)
- {
- __pidfile = malloc(sizeof("/.pid") + (strlen(run) + strlen(name)) * sizeof(char));
- t (__pidfile == NULL);
- stpcpy(stpcpy(stpcpy(stpcpy(__pidfile, run), "/"), name), ".pid");
- }
- else
- {
- __pidfile = malloc(sizeof("/run/.pid") + strlen(name) * sizeof(char));
- t (__pidfile == NULL);
- stpcpy(stpcpy(stpcpy(__pidfile, "/run/"), name), ".pid");
- }
- fd = open(__pidfile, O_WRONLY | O_CREAT | ((flags & DAEMONISE_NEW_PID) ? 0 : O_EXCL), 0644);
- if (fd == -1)
- {
- saved_errno = errno;
- free(__pidfile), __pidfile = NULL;
- errno = saved_errno;
- goto fail;
- }
- pid = getpid();
- t (dprintf(fd, "%lli\n", (long long int)pid) < 0);
- t (close(fd) && (errno != EINTR));
- no_pid_file:
+ /* Become a background process. */
+ t (pid = fork(), pid == -1);
+ close(pipe_rw[!!pid]), pipe_rw[!!pid] = 1;
+ if (pid)
+ exit(read(pipe_rw[0], &fd, (size_t)1) <= 0);
- /* Redirect to '/dev/null'. */
- if (flags & DAEMONISE_KEEP_STDERR)
- closeerr = 0;
- else if (flags & DAEMONISE_CLOSE_STDERR)
- closeerr = 1;
- else
- closeerr = (isatty(2) || (errno == EBADF));
- t (fd = open("/dev/null", O_RDWR), fd == -1);
- if ((flags & DAEMONISE_KEEP_STDIN) == 0) if (fd != 0) close(0);
- if ((flags & DAEMONISE_KEEP_STDOUT) == 0) if (fd != 1) close(1);
- if (closeerr) if (fd != 2) close(2);
- if ((flags & DAEMONISE_KEEP_STDIN) == 0) t (dup2(fd, 0) == -1);
- if ((flags & DAEMONISE_KEEP_STDOUT) == 0) t (dup2(fd, 1) == -1);
- if (closeerr) t (dup2(fd, 2) == -1);
- if (fd > 2)
- close(fd);
- fd = -1;
+ /* Temporarily become session leader. */
+ t (setsid() == -1);
- /* We are done! Let the original process exit. */
- if ((write(pipe_rw[1], &fd, (size_t)1) <= 0) ||
- (close(pipe_rw[1]) && (errno != EINTR)))
- {
- if (flags & DAEMONISE_KEEP_STDERR)
- return -1;
- undaemonise();
- abort(); /* Do not overcomplicate things, just abort in this unlikely event. */
- }
+ /* Fork again. */
+ t (pid = fork(), pid == -1);
+ if (pid > 0)
+ exit(0);
- return 0;
- fail:
- saved_errno = errno;
- if (pipe_rw[0] >= 0) close(pipe_rw[0]);
- if (pipe_rw[1] >= 0) close(pipe_rw[1]);
- if (fd >= 0) close(fd);
- free(keep);
- errno = saved_errno;
- return -1;
+ /* Create PID file. */
+ run = getenv("XDG_RUNTIME_DIR");
+ if (run && *run) {
+ __pidfile = malloc(sizeof("/.pid") + (strlen(run) + strlen(name)) * sizeof(char));
+ t (__pidfile == NULL);
+ stpcpy(stpcpy(stpcpy(stpcpy(__pidfile, run), "/"), name), ".pid");
+ } else {
+ __pidfile = malloc(sizeof("/run/.pid") + strlen(name) * sizeof(char));
+ t (__pidfile == NULL);
+ stpcpy(stpcpy(stpcpy(__pidfile, "/run/"), name), ".pid");
+ }
+ fd = open(__pidfile, O_WRONLY | O_CREAT, 0644);
+ if (fd == -1) {
+ S(free(__pidfile), __pidfile = NULL);
+ goto fail;
+ }
+ pid = getpid();
+ t (dprintf(fd, "%lli\n", (long long int)pid) < 0);
+ t (close(fd) && (errno != EINTR));
+
+ /* Redirect to '/dev/null'. */
+ closeerr = (isatty(2) || (errno == EBADF));
+ t (fd = open("/dev/null", O_RDWR), fd == -1);
+ if (fd != 0) close(0);
+ if (fd != 1) close(1);
+ if (closeerr) if (fd != 2) close(2);
+ t (dup2(fd, 0) == -1);
+ t (dup2(fd, 1) == -1);
+ if (closeerr) t (dup2(fd, 2) == -1);
+ if (fd > 2)
+ close(fd);
+ fd = -1;
+
+ /* We are done! Let the original process exit. */
+ if ((write(pipe_rw[1], &fd, (size_t)1) <= 0) ||
+ (close(pipe_rw[1]) && (errno != EINTR))) {
+ undaemonise();
+ abort(); /* Do not overcomplicate things, just abort in this unlikely event. */
+ }
+
+ return 0;
+fail:
+ return S(close(pipe_rw[0]), close(pipe_rw[1]), close(fd), free(keep)), -1;
}
@@ -412,13 +332,11 @@ int daemonise(const char* name, int flags, ...)
*/
int undaemonise(void)
{
- int r, saved_errno;
- if (__pidfile == NULL)
- return 0;
- r = unlink(__pidfile);
- saved_errno = errno;
- free(__pidfile), __pidfile = NULL;
- errno = saved_errno;
- return r;
+ int r, saved_errno;
+ if (__pidfile == NULL)
+ return 0;
+ r = unlink(__pidfile);
+ S(free(__pidfile), __pidfile = NULL);
+ return r;
}