summaryrefslogtreecommitdiff
path: root/libmailutils/base/daemon.c
diff options
context:
space:
mode:
Diffstat (limited to 'libmailutils/base/daemon.c')
-rw-r--r--libmailutils/base/daemon.c220
1 files changed, 60 insertions, 160 deletions
diff --git a/libmailutils/base/daemon.c b/libmailutils/base/daemon.c
index e9ff80980..4052aae48 100644
--- a/libmailutils/base/daemon.c
+++ b/libmailutils/base/daemon.c
@@ -1,187 +1,87 @@
/* GNU Mailutils -- a suite of utilities for electronic mail
- Copyright (C) 2004-2019 Free Software Foundation, Inc.
+ Copyright (C) 2019-2024 Free Software Foundation, Inc.
- 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 3 of the License, or (at your option) any later version.
+ 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 3, 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.
+ 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, see
- <http://www.gnu.org/licenses/>. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
+ You should have received a copy of the GNU Lesser General Public License
+ along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
+#include <config.h>
+#include <confpaths.h>
#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <string.h>
-
+#include <unistd.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <mailutils/util.h>
#include <mailutils/daemon.h>
-#include <mailutils/errno.h>
-#include <mailutils/error.h>
-#include <mailutils/nls.h>
-
-static char *pidfile;
-static pid_t current_pid;
-
-/* Return 0 if DIR is writable for EUID/EGID.
- Otherwise, return error code. */
-static int
-ewraccess (const char *dir)
-{
- struct stat st;
- if (stat (dir, &st))
- return errno;
- if ((st.st_mode & S_IWOTH)
- || (st.st_gid == getegid () && (st.st_mode & S_IWGRP))
- || (st.st_uid == geteuid () && (st.st_mode & S_IWUSR)))
- return 0;
- else
- return EACCES;
-}
-
-/* Return 0 if DIR is writable. If necessary and possible, raise to
- EUID 0, in that case return prior EUID in the memory location pointed to
- by PUID. */
-static int
-access_dir (const char *dir, uid_t *puid)
-{
- int ec = ewraccess (dir);
- if (ec)
- {
- if (ec == EACCES && access (dir, W_OK) == 0)
- {
- uid_t uid = geteuid ();
- /* See if we can become root */
- if (uid && getuid () == 0 && seteuid (0) == 0)
- {
- *puid = uid;
- return 0;
- }
- }
- }
- return ec;
-}
int
-mu_daemon_create_pidfile (const char *filename)
+mu_daemon (void)
{
- char *p;
int fd;
- uid_t uid = 0;
- int rc;
- if (filename[0] != '/')
- return EINVAL;
+ switch (fork ())
+ {
+ case 0:
+ break;
- if (pidfile)
- free (pidfile);
- pidfile = strdup (filename);
- if (!pidfile)
- return ENOMEM;
+ case -1:
+ return errno;
- /* Determine the hosting directory name */
- p = strrchr (pidfile, '/');
- if (pidfile == p)
- {
- free (pidfile);
- pidfile = NULL;
- /* Sorry, pidfiles in root dir are not allowed */
- return EINVAL;
- }
- /* Check if we have write access to the directory */
- *p = 0;
- rc = access_dir (pidfile, &uid);
- if (rc)
- {
- /* Nope, clean up and return */
- free (pidfile);
- pidfile = NULL;
- return rc;
+ default:
+ _exit (0);
}
- /* Restore directory separator */
- *p = '/';
-
- unlink (pidfile);
- current_pid = getpid ();
+ if (setsid () == (pid_t) -1)
+ return errno;
+
+ signal (SIGHUP, SIG_IGN);
- if ((fd = open (pidfile, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0644)) != -1)
+ switch (fork ())
{
- FILE *fp = fdopen (fd, "w");
- if (!fp)
- {
- rc = errno;
- free (pidfile);
- close (fd);
- }
- else
- {
- fprintf (fp, "%lu", (unsigned long) current_pid);
- fclose (fp);
- atexit (mu_daemon_remove_pidfile);
- }
- }
- else
- {
- rc = errno;
- free (pidfile);
- pidfile = NULL;
- }
+ case 0:
+ break;
- /* Restore previous EUID value. */
- if (uid)
- seteuid (uid);
-
- return rc;
-}
+ case -1:
+ return errno;
-void
-mu_daemon_remove_pidfile (void)
-{
- if (getpid () == current_pid)
- {
- int rc;
- uid_t uid = 0;
+ default:
+ _exit (0);
+ }
- /* Determine the hosting directory name */
- char *p = strrchr (pidfile, '/');
- if (pidfile == p)
- {
- /* Should not happen */
- abort ();
- }
- /* Check if we have write access to the directory */
- *p = 0;
- rc = access_dir (pidfile, &uid);
- *p = '/';
- if (rc == 0)
- {
- if (unlink (pidfile) && errno != ENOENT)
- rc = errno;
- else
- rc = 0;
- }
-
- if (rc)
- mu_error (_("cannot remove pidfile %s: %s"),
- pidfile, mu_strerror (rc));
+ chdir ("/");
+ mu_close_fds (0);
- free (pidfile);
- pidfile = NULL;
+ fd = open (PATH_DEVNULL, O_RDWR);
+ if (fd == 0)
+ {
+ dup2 (fd, 1);
+ dup2 (fd, 2);
+ }
+ else if (fd > 0)
+ {
+ /* This means that mu_close_fds failed to close stdin.
+ Shouldn't happen, but just in case ... */
+ dup2 (fd, 0);
+ dup2 (fd, 1);
+ dup2 (fd, 2);
+ close (fd);
}
+
+ return 0;
}
-
+
+
+
+
+

Return to:

Send suggestions and report system problems to the System administrator.