summaryrefslogtreecommitdiff
path: root/nslcd/daemonize.c
diff options
context:
space:
mode:
Diffstat (limited to 'nslcd/daemonize.c')
-rw-r--r--nslcd/daemonize.c221
1 files changed, 0 insertions, 221 deletions
diff --git a/nslcd/daemonize.c b/nslcd/daemonize.c
deleted file mode 100644
index 0d96f73..0000000
--- a/nslcd/daemonize.c
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- daemoninze.c - functions for properly daemonising an application
-
- Copyright (C) 2014 Arthur de Jong
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301 USA
-*/
-
-#include "config.h"
-
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <string.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#ifdef HAVE_PTHREAD_H
-#include <pthread.h>
-#endif /* HAVE_PTHREAD_H */
-
-#include "daemonize.h"
-#include "log.h"
-
-/* the write end of a pipe that is used to signal the fact that the child
- process has finished initialising (see daemonize_daemon() and
- daemonize_ready() for details) */
-static int daemonizefd = -1;
-
-void daemonize_closefds(void)
-{
- int i;
- /* close all file descriptors (except stdin/out/err) */
- i = sysconf(_SC_OPEN_MAX) - 1;
- /* if the system does not have OPEN_MAX just close the first 32 and
- hope we closed enough */
- if (i < 0)
- i = 32;
- for (; i > 3; i--)
- close(i);
-}
-
-void daemonize_redirect_stdio(void)
-{
- /* close stdin, stdout and stderr */
- close(0); /* stdin */
- close(1); /* stdout */
- close(2); /* stderr */
- /* reconnect to /dev/null */
- open("/dev/null", O_RDWR); /* stdin, fd=0 */
- dup(0); /* stdout, fd=1 */
- dup(0); /* stderr, fd=2 */
-}
-
-/* try to fill the buffer until EOF or error */
-static int read_response(int fd, char *buffer, size_t bufsz)
-{
- int rc;
- size_t r = 0;
- while (r < bufsz)
- {
- rc = read(fd, buffer + r, bufsz - r);
- if (rc == 0)
- break;
- else if (rc > 0)
- r += rc;
- else if ((errno == EINTR) || (errno == EAGAIN))
- continue; /* ignore these errors and try again */
- else
- {
- log_log(LOG_ERR, "read_response(): read() failed: %s", strerror(errno));
- return -1;
- }
- }
- return r;
-}
-
-/* ihe process calling daemonize_daemon() will end up here on success */
-static int wait_for_response(int fd)
-{
- int i, l, rc;
- char buffer[1024];
- /* read return code */
- i = read_response(fd, (void *)&rc, sizeof(int));
- if (i != sizeof(int))
- return -1;
- /* read string length */
- i = read_response(fd, (void *)&l, sizeof(int));
- if ((i != sizeof(int)) || (l <= 0))
- _exit(rc);
- /* read string */
- if ((size_t)l > (sizeof(buffer) - 1))
- l = sizeof(buffer) - 1;
- i = read_response(fd, buffer, l);
- buffer[sizeof(buffer) - 1] = '\0';
- if (i == l)
- fprintf(stderr, "%s", buffer);
- _exit(rc);
-}
-
-static void closefd(void)
-{
- if (daemonizefd >= 0)
- {
- close(daemonizefd);
- daemonizefd = -1;
- }
-}
-
-int daemonize_daemon(void)
-{
- int pipefds[2];
- int i;
- /* set up a pipe for communication */
- if (pipe(pipefds) < 0)
- {
- log_log(LOG_ERR, "pipe() failed: %s", strerror(errno));
- return -1;
- }
- /* set O_NONBLOCK on the write end to ensure that a call to
- daemonize_ready() will not lock the application */
- if ((i = fcntl(pipefds[1], F_GETFL, 0)) < 0)
- {
- log_log(LOG_ERR, "fcntl() failed: %s", strerror(errno));
- close(pipefds[0]);
- close(pipefds[1]);
- return -1;
- }
- if (fcntl(pipefds[1], F_SETFL, i | O_NONBLOCK) < 0)
- {
- log_log(LOG_ERR, "fcntl() failed: %s", strerror(errno));
- close(pipefds[0]);
- close(pipefds[1]);
- return -1;
- }
- /* fork() and exit() to detach from the parent process */
- switch (fork())
- {
- case 0:
- /* we are the child, close read end of pipe */
- close(pipefds[0]);
- break;
- case -1:
- /* we are the parent, but have an error */
- log_log(LOG_ERR, "fork() failed: %s", strerror(errno));
- close(pipefds[0]);
- close(pipefds[1]);
- return -1;
- default:
- /* we are the parent, close write end and wait for information */
- close(pipefds[1]);
- return wait_for_response(pipefds[0]);
- }
- /* become process leader */
- if (setsid() < 0)
- {
- log_log(LOG_ERR, "setsid() failed: %s", strerror(errno));
- close(pipefds[1]);
- _exit(EXIT_FAILURE);
- }
- /* fork again so we cannot allocate a pty */
- switch (fork())
- {
- case 0:
- /* we are the child */
- break;
- case -1:
- /* we are the parent, but have an error */
- log_log(LOG_ERR, "fork() failed: %s", strerror(errno));
- close(pipefds[1]);
- _exit(EXIT_FAILURE);
- default:
- /* we are the parent and we're done */
- close(pipefds[1]);
- _exit(EXIT_SUCCESS);
- }
- daemonizefd = pipefds[1];
- /* close the file descriptor on exec (ignore errors) */
- fcntl(daemonizefd, F_SETFD, FD_CLOEXEC);
-#ifdef HAVE_PTHREAD_ATFORK
- /* handle any other forks by closing daemonizefd first */
- (void)pthread_atfork(NULL, NULL, closefd);
-#endif /* HAVE_PTHREAD_ATFORK */
- return 0;
-}
-
-void daemonize_ready(int status, const char *message)
-{
- if (daemonizefd >= 0)
- {
- /* we ignore any errors writing */
- write(daemonizefd, &status, sizeof(int));
- if ((message == NULL) || (message[0] == '\0'))
- {
- status = 0;
- write(daemonizefd, &status, sizeof(int));
- }
- else
- {
- status = strlen(message);
- write(daemonizefd, &status, sizeof(int));
- write(daemonizefd, message, status);
- }
- close(daemonizefd);
- daemonizefd = -1;
- }
-}