summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/daemon/daemon.820
-rw-r--r--usr.sbin/daemon/daemon.c64
2 files changed, 58 insertions, 26 deletions
diff --git a/usr.sbin/daemon/daemon.8 b/usr.sbin/daemon/daemon.8
index d1d4e35..a8c32f0 100644
--- a/usr.sbin/daemon/daemon.8
+++ b/usr.sbin/daemon/daemon.8
@@ -26,7 +26,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 19, 2007
+.Dd February 19, 2012
.Dt DAEMON 8
.Os
.Sh NAME
@@ -59,14 +59,18 @@ Write the ID of the created process into the
using the
.Xr pidfile 3
functionality.
-If the
+The program is executed in a spawned child process while the
+.Nm
+waits until it terminates to keep the
+.Ar file
+locked and removes it after the process exits.
+The
+.Ar file
+owner is the user who runs the
+.Nm
+regardless of whether the
.Fl u
-option is used, either the pidfile needs to have been pre-created
-with appropriate ownership and permissions, or the directory to contain
-the pidfile must be writable by the specified user.
-Note, that the file will be created shortly before the process is
-actually executed, and will remain after the process exits (although
-it will be removed if the execution fails).
+option is used or not.
.It Fl u Ar user
Login name of the user to execute the program under.
Requires adequate superuser privileges.
diff --git a/usr.sbin/daemon/daemon.c b/usr.sbin/daemon/daemon.c
index 540ebf3..d7e85e5 100644
--- a/usr.sbin/daemon/daemon.c
+++ b/usr.sbin/daemon/daemon.c
@@ -32,6 +32,7 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/wait.h>
#include <err.h>
#include <errno.h>
@@ -43,15 +44,16 @@ __FBSDID("$FreeBSD$");
#include <unistd.h>
static void restrict_process(const char *);
+static void wait_child(pid_t pid);
static void usage(void);
int
main(int argc, char *argv[])
{
struct pidfh *pfh = NULL;
- int ch, nochdir, noclose, errcode;
+ int ch, nochdir, noclose;
const char *pidfile, *user;
- pid_t otherpid;
+ pid_t otherpid, pid;
nochdir = noclose = 1;
pidfile = user = NULL;
@@ -79,14 +81,12 @@ main(int argc, char *argv[])
if (argc == 0)
usage();
- if (user != NULL)
- restrict_process(user);
-
+ pfh = NULL;
/*
* Try to open the pidfile before calling daemon(3),
* to be able to report the error intelligently
*/
- if (pidfile) {
+ if (pidfile != NULL) {
pfh = pidfile_open(pidfile, 0600, &otherpid);
if (pfh == NULL) {
if (errno == EEXIST) {
@@ -100,22 +100,37 @@ main(int argc, char *argv[])
if (daemon(nochdir, noclose) == -1)
err(1, NULL);
- /* Now that we are the child, write out the pid */
- if (pidfile)
+ pid = 0;
+ if (pidfile != NULL) {
+ /*
+ * Spawn a child to exec the command, so in the parent
+ * we could wait for it to exit and remove pidfile.
+ */
+ pid = fork();
+ if (pid == -1) {
+ pidfile_remove(pfh);
+ err(1, "fork");
+ }
+ }
+ if (pid == 0) {
+ /* Now that we are the child, write out the pid. */
pidfile_write(pfh);
- execvp(argv[0], argv);
+ if (user != NULL)
+ restrict_process(user);
- /*
- * execvp() failed -- unlink pidfile if any, and
- * report the error
- */
- errcode = errno; /* Preserve errcode -- unlink may reset it */
- if (pidfile)
- pidfile_remove(pfh);
+ execvp(argv[0], argv);
- /* The child is now running, so the exit status doesn't matter. */
- errc(1, errcode, "%s", argv[0]);
+ /*
+ * execvp() failed -- report the error. The child is
+ * now running, so the exit status doesn't matter.
+ */
+ err(1, "%s", argv[0]);
+ }
+ setproctitle("%s[%d]", argv[0], pid);
+ wait_child(pid);
+ pidfile_remove(pfh);
+ exit(0); /* Exit status does not matter. */
}
static void
@@ -132,6 +147,19 @@ restrict_process(const char *user)
}
static void
+wait_child(pid_t pid)
+{
+ int status;
+
+ while (waitpid(pid, &status, 0) == -1) {
+ if (errno != EINTR) {
+ warn("waitpid");
+ break;
+ }
+ }
+}
+
+static void
usage(void)
{
(void)fprintf(stderr,
OpenPOWER on IntegriCloud