Skip site navigation (1)Skip section navigation (2)
Date:      Fri,  3 Nov 2006 11:26:32 +0200 (EET)
From:      Tomas Verbaitis <tomasv@megalogika.lt>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   misc/105103: request to merge pidfile(3) and daemon(8) to 4-STABLE
Message-ID:  <20061103092632.66E9D4325@pilvas.lan>
Resent-Message-ID: <200611030930.kA39ULCi060853@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         105103
>Category:       misc
>Synopsis:       request to merge pidfile(3) and daemon(8) to 4-STABLE
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Fri Nov 03 09:30:21 GMT 2006
>Closed-Date:
>Last-Modified:
>Originator:     Tomas Verbaitis
>Release:        FreeBSD 4.11-STABLE i386
>Organization:
Megalogika Ltd., http://megalogika.lt
>Environment:
System: FreeBSD stroike.lan 4.11-STABLE FreeBSD 4.11-STABLE #2: Wed Oct  4 14:05:39 GMT 2006
tomasv@stroike.lan:/usr/obj/usr/src/sys/STROIKE  i386

>Description:
        In order to use www/tomcat55 and other Apache Tomcat ports on 4-STABLE 
        daemon(8) functionality to write daemonized process' PID to file
	(-p option) is needed.
>How-To-Repeat:
        Install www/tomcat55 on 4-STABLE
        Try to launch Tomcat using provided rc script
        Or just try daemon -p 1020 ls -l 
>Fix:
        Provided is a patch which merges required functionality to 4-STABLE

diff -u -ruN /usr/src/sys/sys/errno.h /usr/local/src/FreeBSD/sys/sys/errno.h
--- /usr/src/sys/sys/errno.h    Wed Jan 12 18:34:54 2005
+++ /usr/local/src/FreeBSD/sys/sys/errno.h  Thu Nov  2 19:05:42 2006
@@ -168,7 +168,8 @@
 #define    ECANCELED   85      /* Operation canceled */
 #define    EILSEQ      86      /* Illegal byte sequence */
 #define    ENOATTR     87      /* Attribute not found */
-#define    ELAST       87      /* Must be equal largest errno */
+#define    EDOOFUS     88      /* Programming error */
+#define    ELAST       88      /* Must be equal largest errno */
 
 #endif /* _POSIX_SOURCE */
 
diff -u -ruN /usr/src/sys/sys/types.h /usr/local/src/FreeBSD/sys/sys/types.h
--- /usr/src/sys/sys/types.h    Sat Apr 21 17:53:06 2001
+++ /usr/local/src/FreeBSD/sys/sys/types.h  Thu Nov  2 19:05:42 2006
@@ -108,6 +108,7 @@
 typedef    u_int32_t   dev_t;      /* device number */
 #define udev_t dev_t
 
+typedef __uint32_t      __dev_t;   /* device number or struct cdev */
 #ifndef _POSIX_SOURCE
 
 /*
diff -u -ruN /usr/src/lib/libutil/Makefile /usr/local/src/FreeBSD/lib/libutil/Makefile
--- /usr/src/lib/libutil/Makefile   Wed Apr 25 13:04:42 2001
+++ /usr/local/src/FreeBSD/lib/libutil/Makefile Wed Oct 18 15:03:57 2006
@@ -9,13 +9,13 @@
 SRCS=  login.c login_tty.c logout.c logwtmp.c pty.c \
    login_cap.c login_class.c login_auth.c login_times.c login_ok.c \
    login_crypt.c _secure_path.c uucplock.c property.c auth.c \
-   realhostname.c fparseln.c stub.c
+   realhostname.c fparseln.c stub.c pidfile.c
 INCS=  libutil.h login_cap.h
 
 MAN+=  login.3 login_auth.3 login_tty.3 logout.3 logwtmp.3 pty.3 \
    login_cap.3 login_class.3 login_times.3 login_ok.3 \
    _secure_path.3 uucplock.3 property.3 auth.3 realhostname.3 \
-   realhostname_sa.3 trimdomain.3 fparseln.3
+   realhostname_sa.3 trimdomain.3 fparseln.3 pidfile.3
 MAN+=  login.conf.5 auth.conf.5
 MLINKS+= property.3 properties_read.3  property.3 properties_free.3
 MLINKS+= property.3 property_find.3
@@ -38,5 +38,9 @@
 MLINKS+=login_auth.3 auth_checknologin.3 login_auth.3 auth_cat.3
 MLINKS+=uucplock.3 uu_lock.3 uucplock.3 uu_lock_txfr.3 \
    uucplock.3 uu_unlock.3 uucplock.3 uu_lockerr.3
+MLINKS+=pidfile.3 pidfile_open.3 \
+   pidfile.3 pidfile_write.3 \
+   pidfile.3 pidfile_close.3 \
+   pidfile.3 pidfile_remove.3
 
 .include <bsd.lib.mk>
diff -u -ruN /usr/src/lib/libutil/libutil.h /usr/local/src/FreeBSD/lib/libutil/libutil.h
--- /usr/src/lib/libutil/libutil.h  Wed Nov 22 05:49:49 2000
+++ /usr/local/src/FreeBSD/lib/libutil/libutil.h    Wed Oct 18 15:06:30 2006
@@ -41,6 +41,16 @@
    char *value;
 } *properties;
 
+#ifdef _SYS_PARAM_H_
+/* for pidfile.c */
+struct pidfh {
+   int pf_fd;
+   char    pf_path[MAXPATHLEN + 1];
+   __dev_t pf_dev;
+   ino_t   pf_ino;
+};
+#endif
+
 /* Avoid pulling in all the include files for no need */
 struct termios;
 struct winsize;
@@ -73,6 +83,14 @@
 #ifdef _STDIO_H_   /* avoid adding new includes */
 char   *fparseln __P((FILE *, size_t *, size_t *, const char[3], int));
 #endif
+
+#ifdef _SYS_PARAM_H_
+struct pidfh *pidfile_open(const char *path, mode_t mode, pid_t *pidptr);
+int pidfile_write(struct pidfh *pfh);
+int pidfile_close(struct pidfh *pfh);
+int pidfile_remove(struct pidfh *pfh);
+#endif
+
 __END_DECLS
 
 #define UU_LOCK_INUSE (1)
diff -u -ruN /usr/src/lib/libutil/pidfile.3 /usr/local/src/FreeBSD/lib/libutil/pidfile.3
--- /usr/src/lib/libutil/pidfile.3  Thu Jan  1 02:00:00 1970
+++ /usr/local/src/FreeBSD/lib/libutil/pidfile.3    Wed Oct 18 15:01:24 2006
@@ -0,0 +1,249 @@
+.\" Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD: src/lib/libutil/pidfile.3,v 1.5 2006/03/04 15:20:28 keramida Exp $
+.\"
+.Dd August 22, 2005
+.Dt PIDFILE 3
+.Os
+.Sh NAME
+.Nm pidfile_open ,
+.Nm pidfile_write ,
+.Nm pidfile_close ,
+.Nm pidfile_remove
+.Nd "library for PID files handling"
+.Sh LIBRARY
+.Lb libutil
+.Sh SYNOPSIS
+.In sys/param.h
+.In libutil.h
+.Ft "struct pidfh *"
+.Fn pidfile_open "const char *path" "mode_t mode" "pid_t *pidptr"
+.Ft int
+.Fn pidfile_write "struct pidfh *pfh"
+.Ft int
+.Fn pidfile_close "struct pidfh *pfh"
+.Ft int
+.Fn pidfile_remove "struct pidfh *pfh"
+.Sh DESCRIPTION
+The
+.Nm pidfile
+family of functions allows daemons to handle PID files.
+It uses
+.Xr flock 2
+to lock a pidfile and detect already running daemons.
+.Pp
+The
+.Fn pidfile_open
+function opens (or creates) a file specified by the
+.Fa path
+argument and locks it with the
+.Xr flock 2
+system call.
+If a file can not be locked, a PID of an already running daemon is returned in
+the
+.Fa pidptr
+argument (if it is not
+.Dv NULL ) .
+The function does not write process' PID into the file here, so it can be
+used before
+.Fn fork Ns ing
+and exit with a proper error message when needed.
+If the
+.Fa path
+argument is
+.Dv NULL ,
+.Pa /var/run/ Ns Ao Va progname Ac Ns Pa .pid
+file will be used.
+.Pp
+The
+.Fn pidfile_write
+function writes process' PID into a previously opened file.
+.Pp
+The
+.Fn pidfile_close
+function closes a pidfile.
+It should be used after daemon
+.Fn fork Ns s
+to start a child process.
+.Pp
+The
+.Fn pidfile_remove
+function closes and removes a pidfile.
+.Sh RETURN VALUES
+The
+.Fn pidfile_open
+function returns a valid pointer to a
+.Vt pidfh
+structure on success, or
+.Dv NULL
+if an error occurs.
+If an error occurs,
+.Va errno
+will be set.
+.Rv -std pidfile_write pidfile_close pidfile_remove
+.Sh EXAMPLES
+The following example shows in which order these functions should be used.
+Note that it is safe to pass
+.Dv NULL
+to
+.Fn pidfile_write ,
+.Fn pidfile_remove
+and
+.Fn pidfile_close
+functions.
+.Bd -literal
+struct pidfh *pfh;
+pid_t otherpid, childpid;
+
+pfh = pidfile_open("/var/run/daemon.pid", 0600, &otherpid);
+if (pfh == NULL) {
+   if (errno == EEXIST) {
+       errx(EXIT_FAILURE, "Daemon already running, pid: %jd.",
+           (intmax_t)otherpid);
+   }
+   /* If we cannot create pidfile from other reasons, only warn. */
+   warn("Cannot open or create pidfile");
+}
+
+if (daemon(0, 0) == -1) {
+   warn("Cannot daemonize");
+   pidfile_remove(pfh);
+   exit(EXIT_FAILURE);
+}
+
+pidfile_write(pfh);
+
+for (;;) {
+   /* Do work. */
+   childpid = fork();
+   switch (childpid) {
+   case -1:
+       syslog(LOG_ERR, "Cannot fork(): %s.", strerror(errno));
+       break;
+   case 0:
+       pidfile_close(pfh);
+       /* Do child work. */
+       break;
+   default:
+       syslog(LOG_INFO, "Child %jd started.", (intmax_t)childpid);
+       break;
+   }
+}
+
+pidfile_remove(pfh);
+exit(EXIT_SUCCESS);
+.Ed
+.Sh ERRORS
+The
+.Fn pidfile_open
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EEXIST
+Some process already holds the lock on the given pidfile, meaning that a
+daemon is already running.
+.It Bq Er ENAMETOOLONG
+Specified pidfile's name is too long.
+.It Bq Er EINVAL
+Some process already holds the lock on the given pidfile, but PID read
+from there is invalid.
+.El
+.Pp
+The
+.Fn pidfile_open
+function may also fail and set
+.Va errno
+for any errors specified for the
+.Xr fstat 2 ,
+.Xr open 2 ,
+and
+.Xr read 2
+calls.
+.Pp
+The
+.Fn pidfile_write
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EDOOFUS
+Improper function use.
+Probably called before
+.Fn pidfile_open .
+.El
+.Pp
+The
+.Fn pidfile_write
+function may also fail and set
+.Va errno
+for any errors specified for the
+.Xr fstat 2 ,
+.Xr ftruncate 2 ,
+and
+.Xr write 2
+calls.
+.Pp
+The
+.Fn pidfile_close
+function may fail and set
+.Va errno
+for any errors specified for the
+.Xr close 2
+and
+.Xr fstat 2
+calls.
+.Pp
+The
+.Fn pidfile_remove
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EDOOFUS
+Improper function use.
+Probably called not from the process which made
+.Fn pidfile_write .
+.El
+.Pp
+The
+.Fn pidfile_remove
+function may also fail and set
+.Va errno
+for any errors specified for the
+.Xr close 2 ,
+.Xr flock 2 ,
+.Xr fstat 2 ,
+.Xr write 2 ,
+and
+.Xr unlink 2
+calls.
+.Sh SEE ALSO
+.Xr flock 2 ,
+.Xr open 2 ,
+.Xr daemon 3
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm pidfile
+functionality is based on ideas from
+.An John-Mark Gurney Aq jmg@FreeBSD.org .
+.Pp
+The code and manual page was written by
+.An Pawel Jakub Dawidek Aq pjd@FreeBSD.org .
diff -u -ruN /usr/src/lib/libutil/pidfile.c /usr/local/src/FreeBSD/lib/libutil/pidfile.c
--- /usr/src/lib/libutil/pidfile.c  Thu Jan  1 02:00:00 1970
+++ /usr/local/src/FreeBSD/lib/libutil/pidfile.c    Wed Oct 18 15:01:24 2006
@@ -0,0 +1,244 @@
+/*-
+ * Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libutil/pidfile.c,v 1.3 2006/06/23 01:42:03 brian Exp $");
+
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <err.h>
+#include <errno.h>
+#include <libutil.h>
+
+static int _pidfile_remove(struct pidfh *pfh, int freeit);
+
+static int
+pidfile_verify(struct pidfh *pfh)
+{
+   struct stat sb;
+
+   if (pfh == NULL || pfh->pf_fd == -1)
+       return (EDOOFUS);
+   /*
+    * Check remembered descriptor.
+    */
+   if (fstat(pfh->pf_fd, &sb) == -1)
+       return (errno);
+   if (sb.st_dev != pfh->pf_dev || sb.st_ino != pfh->pf_ino)
+       return (EDOOFUS);
+   return (0);
+}
+
+static int
+pidfile_read(const char *path, pid_t *pidptr)
+{
+   char buf[16], *endptr;
+   int error, fd, i;
+
+   fd = open(path, O_RDONLY);
+   if (fd == -1)
+       return (errno);
+
+   i = read(fd, buf, sizeof(buf) - 1);
+   error = errno;  /* Remember errno in case close() wants to change it. */
+   close(fd);
+   if (i == -1)
+       return (error);
+   buf[i] = '\0';
+
+   *pidptr = strtol(buf, &endptr, 10);
+   if (endptr != &buf[i])
+       return (EINVAL);
+
+   return (0);
+}
+
+struct pidfh *
+pidfile_open(const char *path, mode_t mode, pid_t *pidptr)
+{
+   struct pidfh *pfh;
+   struct stat sb;
+   int error, fd;
+
+   pfh = malloc(sizeof(*pfh));
+   if (pfh == NULL)
+       return (NULL);
+
+   if (path == NULL) {
+       snprintf(pfh->pf_path, sizeof(pfh->pf_path), "/var/run/%s.pid",
+           getprogname());
+   } else {
+       strlcpy(pfh->pf_path, path, sizeof(pfh->pf_path));
+   }
+   if (strlen(pfh->pf_path) == sizeof(pfh->pf_path) - 1) {
+       free(pfh);
+       errno = ENAMETOOLONG;
+       return (NULL);
+   }
+
+   /*
+    * Open the PID file and obtain exclusive lock.
+    * We truncate PID file here only to remove old PID immediatelly,
+    * PID file will be truncated again in pidfile_write(), so
+    * pidfile_write() can be called multiple times.
+    */
+   fd = open(pfh->pf_path,
+       O_WRONLY | O_CREAT | O_EXLOCK | O_TRUNC | O_NONBLOCK, mode);
+   if (fd == -1) {
+       if (errno == EWOULDBLOCK && pidptr != NULL) {
+           errno = pidfile_read(pfh->pf_path, pidptr);
+           if (errno == 0)
+               errno = EEXIST;
+       }
+       free(pfh);
+       return (NULL);
+   }
+   /*
+    * Remember file information, so in pidfile_write() we are sure we write
+    * to the proper descriptor.
+    */
+   if (fstat(fd, &sb) == -1) {
+       error = errno;
+       unlink(pfh->pf_path);
+       close(fd);
+       free(pfh);
+       errno = error;
+       return (NULL);
+   }
+
+   pfh->pf_fd = fd;
+   pfh->pf_dev = sb.st_dev;
+   pfh->pf_ino = sb.st_ino;
+
+   return (pfh);
+}
+
+int
+pidfile_write(struct pidfh *pfh)
+{
+   char pidstr[16];
+   int error, fd;
+
+   /*
+    * Check remembered descriptor, so we don't overwrite some other
+    * file if pidfile was closed and descriptor reused.
+    */
+   errno = pidfile_verify(pfh);
+   if (errno != 0) {
+       /*
+        * Don't close descriptor, because we are not sure if it's ours.
+        */
+       return (-1);
+   }
+   fd = pfh->pf_fd;
+
+   /*
+    * Truncate PID file, so multiple calls of pidfile_write() are allowed.
+    */
+   if (ftruncate(fd, 0) == -1) {
+       error = errno;
+       _pidfile_remove(pfh, 0);
+       errno = error;
+       return (-1);
+   }
+
+   snprintf(pidstr, sizeof(pidstr), "%u", getpid());
+   if (pwrite(fd, pidstr, strlen(pidstr), 0) != (ssize_t)strlen(pidstr)) {
+       error = errno;
+       _pidfile_remove(pfh, 0);
+       errno = error;
+       return (-1);
+   }
+
+   return (0);
+}
+
+int
+pidfile_close(struct pidfh *pfh)
+{
+   int error;
+
+   error = pidfile_verify(pfh);
+   if (error != 0) {
+       errno = error;
+       return (-1);
+   }
+
+   if (close(pfh->pf_fd) == -1)
+       error = errno;
+   free(pfh);
+   if (error != 0) {
+       errno = error;
+       return (-1);
+   }
+   return (0);
+}
+
+static int
+_pidfile_remove(struct pidfh *pfh, int freeit)
+{
+   int error;
+
+   error = pidfile_verify(pfh);
+   if (error != 0) {
+       errno = error;
+       return (-1);
+   }
+
+   if (unlink(pfh->pf_path) == -1)
+       error = errno;
+   if (flock(pfh->pf_fd, LOCK_UN) == -1) {
+       if (error == 0)
+           error = errno;
+   }
+   if (close(pfh->pf_fd) == -1) {
+       if (error == 0)
+           error = errno;
+   }
+   if (freeit)
+       free(pfh);
+   else
+       pfh->pf_fd = -1;
+   if (error != 0) {
+       errno = error;
+       return (-1);
+   }
+   return (0);
+}
+
+int
+pidfile_remove(struct pidfh *pfh)
+{
+
+   return (_pidfile_remove(pfh, 1));
+}
diff -u -ruN /usr/src/usr.sbin/daemon/Makefile /usr/local/src/FreeBSD/usr.sbin/daemon/Makefile
--- /usr/src/usr.sbin/daemon/Makefile   Wed Aug 28 20:25:54 2002
+++ /usr/local/src/FreeBSD/usr.sbin/daemon/Makefile Wed Oct 18 15:14:40 2006
@@ -1,7 +1,11 @@
-# $FreeBSD: src/usr.sbin/daemon/Makefile,v 1.1.2.1 2002/08/28 17:25:54 sheldonh Exp $
+# $FreeBSD: src/usr.sbin/daemon/Makefile,v 1.3 2005/08/24 17:24:39 pjd Exp $
 
 PROG=  daemon
-WARNS?=    2
 MAN=   daemon.8
+
+DPADD= ${LIBUTIL}
+LDADD= -lutil
+
+WARNS?=    2
 
 .include <bsd.prog.mk>
diff -u -ruN /usr/src/usr.sbin/daemon/daemon.8 /usr/local/src/FreeBSD/usr.sbin/daemon/daemon.8
--- /usr/src/usr.sbin/daemon/daemon.8   Wed Feb  5 05:30:32 2003
+++ /usr/local/src/FreeBSD/usr.sbin/daemon/daemon.8 Wed Oct 18 15:14:40 2006
@@ -24,7 +24,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\" $FreeBSD: src/usr.sbin/daemon/daemon.8,v 1.2.2.2 2003/02/05 03:30:32 trhodes Exp $
+.\" $FreeBSD: src/usr.sbin/daemon/daemon.8,v 1.7 2005/08/24 17:24:39 pjd Exp $
 .\"
 .Dd August 30, 2001
 .Dt DAEMON 8
@@ -35,6 +35,7 @@
 .Sh SYNOPSIS
 .Nm
 .Op Fl cf
+.Op Fl p Ar pidfile
 .Ar command arguments ...
 .Sh DESCRIPTION
 The
@@ -50,13 +51,27 @@
 .It Fl f
 Redirect standard input, standard output and standard error to
 .Pa /dev/null .
+.It Fl p Ar file
+Write the ID of the created process into the
+.Ar file
+using
+.Xr pidfile 3
+functionality.
+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).
 .El
-.Sh DIAGNOSTICS
+.Sh EXIT STATUS
 The
 .Nm
 utility exits 1 if an error is returned by the
 .Xr daemon 3
-library routine, otherwise 0.
+library routine, 2 if the
+.Ar pidfile
+is requested, but cannot be opened, 3 if process is already running (pidfile
+exists and is locked),
+otherwise 0.
+.Sh DIAGNOSTICS
 If the command cannot be executed, an error message is displayed on
 standard error unless the
 .Fl f
@@ -64,6 +79,7 @@
 .Sh SEE ALSO
 .Xr daemon 3 ,
 .Xr exec 3 ,
+.Xr pidfile 3 ,
 .Xr termios 4 ,
 .Xr tty 4
 .Sh HISTORY
diff -u -ruN /usr/src/usr.sbin/daemon/daemon.c /usr/local/src/FreeBSD/usr.sbin/daemon/daemon.c
--- /usr/src/usr.sbin/daemon/daemon.c   Wed Aug 28 20:25:54 2002
+++ /usr/local/src/FreeBSD/usr.sbin/daemon/daemon.c Wed Oct 18 15:14:40 2006
@@ -26,12 +26,16 @@
  * SUCH DAMAGE.
  *
  * From BSDI: daemon.c,v 1.2 1996/08/15 01:11:09 jch Exp
- * $FreeBSD: src/usr.sbin/daemon/daemon.c,v 1.1.2.1 2002/08/28 17:25:54 sheldonh Exp $
  */
 
-#include <sys/types.h>
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/usr.sbin/daemon/daemon.c,v 1.4 2005/08/24 17:24:39 pjd Exp $");
+
+#include <sys/param.h>
 
 #include <err.h>
+#include <errno.h>
+#include <libutil.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -41,10 +45,14 @@
 int
 main(int argc, char *argv[])
 {
-   int ch, nochdir, noclose;
+   struct pidfh *pfh;
+   int ch, nochdir, noclose, errcode;
+   const char *pidfile;
+   pid_t otherpid;
 
    nochdir = noclose = 1;
-   while ((ch = getopt(argc, argv, "-cf")) != -1) {
+   pidfile = NULL;
+   while ((ch = getopt(argc, argv, "-cfp:")) != -1) {
        switch (ch) {
        case 'c':
            nochdir = 0;
@@ -52,7 +60,9 @@
        case 'f':
            noclose = 0;
            break;
-       case '?':
+       case 'p':
+           pidfile = optarg;
+           break;
        default:
            usage();
        }
@@ -62,17 +72,46 @@
 
    if (argc == 0)
        usage();
+   /*
+    * Try to open the pidfile before calling daemon(3),
+    * to be able to report the error intelligently
+    */
+   if (pidfile) {
+       pfh = pidfile_open(pidfile, 0600, &otherpid);
+       if (pfh == NULL) {
+           if (errno == EEXIST) {
+               errx(3, "process already running, pid: %d",
+                   otherpid);
+           }
+           err(2, "pidfile ``%s''", pidfile);
+       }
+   }
+
    if (daemon(nochdir, noclose) == -1)
        err(1, NULL);
+
+   /* Now that we are the child, write out the pid */
+   if (pidfile)
+       pidfile_write(pfh);
+
    execvp(argv[0], argv);
 
+   /*
+    * execvp() failed -- unlink pidfile if any, and
+    * report the error
+    */
+   errcode = errno; /* Preserve errcode -- unlink may reset it */
+   if (pidfile)
+       pidfile_remove(pfh);
+
    /* The child is now running, so the exit status doesn't matter. */
-   err(1, "%s", argv[0]);
+   errc(1, errcode, "%s", argv[0]);
 }
 
 static void
 usage(void)
 {
-   (void)fprintf(stderr, "usage: daemon [-cf] command arguments ...\n");
+   (void)fprintf(stderr,
+       "usage: daemon [-cf] [-p pidfile] command arguments ...\n");
    exit(1);
 }

>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20061103092632.66E9D4325>