Index: src/distrib/sets/lists/base/shl.mi
===================================================================
RCS file: /bracket/repo/src/distrib/sets/lists/base/shl.mi,v
retrieving revision 1.687
diff -u -r1.687 shl.mi
--- src/distrib/sets/lists/base/shl.mi	17 Jan 2014 00:00:05 -0000	1.687
+++ src/distrib/sets/lists/base/shl.mi	28 Jan 2014 12:05:35 -0000
@@ -15,7 +15,7 @@
 #
 ./lib/libc.so					base-sys-shlib		dynamicroot
 ./lib/libc.so.12				base-sys-shlib		dynamicroot
-./lib/libc.so.12.189				base-sys-shlib		dynamicroot
+./lib/libc.so.12.190				base-sys-shlib		dynamicroot
 ./lib/libcrypt.so				base-sys-shlib		dynamicroot
 ./lib/libcrypt.so.1				base-sys-shlib		dynamicroot
 ./lib/libcrypt.so.1.0				base-sys-shlib		dynamicroot
@@ -197,7 +197,7 @@
 ./usr/lib/libc++.so.1.0				base-sys-shlib		libcxx
 ./usr/lib/libc.so				base-sys-shlib
 ./usr/lib/libc.so.12				base-sys-shlib
-./usr/lib/libc.so.12.189			base-sys-shlib
+./usr/lib/libc.so.12.190			base-sys-shlib
 ./usr/lib/libcdk.so				base-obsolete		obsolete
 ./usr/lib/libcom_err.so				base-krb5-shlib		kerberos
 ./usr/lib/libcom_err.so.7			base-krb5-shlib		kerberos
Index: src/distrib/sets/lists/tests/mi
===================================================================
RCS file: /bracket/repo/src/distrib/sets/lists/tests/mi,v
retrieving revision 1.559
diff -u -r1.559 mi
--- src/distrib/sets/lists/tests/mi	17 Jan 2014 22:34:36 -0000	1.559
+++ src/distrib/sets/lists/tests/mi	27 Jan 2014 14:41:29 -0000
@@ -1884,11 +1884,13 @@
 ./usr/tests/lib/libc/gen/posix_spawn/t_fileactions	tests-kernel-tests	atf
 ./usr/tests/lib/libc/gen/posix_spawn/t_spawn		tests-kernel-tests	atf
 ./usr/tests/lib/libc/gen/posix_spawn/t_spawnattr	tests-kernel-tests	atf
+./usr/tests/lib/libc/gen/h_daemon2		tests-lib-tests		atf
 ./usr/tests/lib/libc/gen/t_alarm		tests-lib-tests		atf
 ./usr/tests/lib/libc/gen/t_assert		tests-lib-tests		atf
 ./usr/tests/lib/libc/gen/t_basedirname		tests-lib-tests		atf
 ./usr/tests/lib/libc/gen/t_closefrom		tests-lib-tests		atf
 ./usr/tests/lib/libc/gen/t_cpuset		tests-lib-tests		atf
+./usr/tests/lib/libc/gen/t_daemon2		tests-lib-tests		atf
 ./usr/tests/lib/libc/gen/t_dir			tests-lib-tests		atf
 ./usr/tests/lib/libc/gen/t_fmtcheck		tests-lib-tests		atf
 ./usr/tests/lib/libc/gen/t_fnmatch		tests-lib-tests		atf
Index: src/include/stdlib.h
===================================================================
RCS file: /bracket/repo/src/include/stdlib.h,v
retrieving revision 1.107
diff -u -r1.107 stdlib.h
--- src/include/stdlib.h	8 Jan 2014 02:16:03 -0000	1.107
+++ src/include/stdlib.h	27 Jan 2014 14:41:29 -0000
@@ -276,6 +276,8 @@
 void	 csetexpandtc(int);
 
 int	 daemon(int, int);
+int	 daemon2_fork(void);
+int	 daemon2_detach(int, int);
 int	 devname_r(dev_t, mode_t, char *, size_t);
 #ifndef __LIBC12_SOURCE__
 __aconst char *devname(dev_t, mode_t) __RENAME(__devname50);
Index: src/lib/libc/shlib_version
===================================================================
RCS file: /bracket/repo/src/lib/libc/shlib_version,v
retrieving revision 1.248
diff -u -r1.248 shlib_version
--- src/lib/libc/shlib_version	16 Jan 2014 17:21:38 -0000	1.248
+++ src/lib/libc/shlib_version	27 Jan 2014 15:10:17 -0000
@@ -40,4 +40,4 @@
 # - consolidate ownership with crt0.o and avoid common symbols
 # - redo stdin/stdout/stderr to not require copy relocations
 major=12
-minor=189
+minor=190
Index: src/lib/libc/gen/Makefile.inc
===================================================================
RCS file: /bracket/repo/src/lib/libc/gen/Makefile.inc,v
retrieving revision 1.187
diff -u -r1.187 Makefile.inc
--- src/lib/libc/gen/Makefile.inc	16 Jan 2014 20:31:42 -0000	1.187
+++ src/lib/libc/gen/Makefile.inc	27 Jan 2014 14:41:29 -0000
@@ -6,7 +6,7 @@
 
 SRCS+= 	_errno.c alarm.c alphasort.c arc4random.c assert.c basename.c clock.c \
 	closedir.c closefrom.c \
-	confstr.c ctermid.c ctype_.c daemon.c \
+	confstr.c ctermid.c ctype_.c daemon.c daemon2.c \
 	dehumanize_number.c devname.c dirname.c disklabel.c err.c errx.c \
 	errc.c errlist.c errno.c execl.c execle.c execlp.c execv.c execvp.c \
 	extattr.c fmtcheck.c fmtmsg.c fnmatch.c fstab.c ftok.c \
Index: src/lib/libc/gen/daemon.3
===================================================================
RCS file: /bracket/repo/src/lib/libc/gen/daemon.3,v
retrieving revision 1.15
diff -u -r1.15 daemon.3
--- src/lib/libc/gen/daemon.3	7 Aug 2003 16:42:46 -0000	1.15
+++ src/lib/libc/gen/daemon.3	27 Jan 2014 14:41:29 -0000
@@ -41,6 +41,10 @@
 .In stdlib.h
 .Ft int
 .Fn daemon "int nochdir" "int noclose"
+.Ft int
+.Fn daemon2_fork
+.Ft int
+.Fn daemon2_detach "int nochdir" "int noclose"
 .Sh DESCRIPTION
 The
 .Fn daemon
@@ -61,6 +65,39 @@
 will redirect standard input, standard output and standard error
 to
 .Pa /dev/null .
+.Pp
+The
+.Fn daemon2_fork
+and
+.Fn daemon2_detach
+functions divide the functionality of
+.Fn daemon
+into two parts, and are called in that order.
+On return from 
+.Fn daemon2_fork ,
+the process has forked and is executing in the child context,
+but will not detach from its controlling terminal, close
+streams, or change working directory until
+.Fn daemon2_detach
+is called.
+.Pp
+Typically,
+.Fn daemon2_fork
+is called early in the daemon process,
+before creating sockets, kqueues, or threads, and 
+.Fn daemon2_detach
+is called once the daemon is fully initialized and ready to service
+requests.  Any errors that occur between the two calls may be reported
+using the standard error stream.
+.Pp
+When using
+.Fn daemon2_fork ,
+the parent process only exits after the child calls
+.Fn daemon2_detach
+or exits, whichever happens first.  The exit status of the parent
+process is 0 if
+.Fn daemon2_detach
+was called, or 1 otherwise.
 .Sh RETURN VALUES
 On return 0 indicates success with \-1 indicating error.
 .Sh ERRORS
@@ -72,6 +109,24 @@
 .Xr fork 2
 and
 .Xr setsid 2 .
+.Pp
+The function
+.Fn daemon2_fork
+may fail and set
+.Va errno
+for any of the errors specified for the library functions
+.Xr fork 2
+and
+.Xr pipe 2 .
+.Pp
+The function
+.Fn daemon2_detach
+may fail and set
+.Va errno
+for any of the errors specified for the library functions
+.Xr write 2
+and
+.Xr setsid 2 .
 .Sh SEE ALSO
 .Xr fork 2 ,
 .Xr setsid 2
@@ -80,6 +135,13 @@
 .Fn daemon
 function first appeared in
 .Bx 4.4 .
+.Pp
+The
+.Fn daemon2_fork
+and
+.Fn daemon2_detach
+functions first appeared in
+.Nx 7 .
 .Sh CAVEATS
 Unless the
 .Ar noclose
Index: src/lib/libc/gen/daemon2.c
===================================================================
RCS file: src/lib/libc/gen/daemon2.c
diff -N src/lib/libc/gen/daemon2.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/lib/libc/gen/daemon2.c	28 Jan 2014 10:16:17 -0000
@@ -0,0 +1,151 @@
+/*	$NetBSD: daemon.c,v 1.10 2012/06/25 22:32:43 abs Exp $	*/
+
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  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.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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>
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)daemon.c	8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: daemon.c,v 1.10 2012/06/25 22:32:43 abs Exp $");
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#include "namespace.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+/*
+ * Pipe for signalling between the child and parent process.  Writing
+ * a byte (of any value) to the pipe signals to the parent process
+ * that the daemon is ready to provide service.
+ */
+int __daemon2_detach_pipe[2];
+
+int
+daemon2_fork(void)
+{
+	int r;
+	int fd;
+	int i;
+
+	/*
+	 * Set up the pipe, making sure the write end does not
+	 * get allocated one of the file descriptors that will
+	 * be closed in daemon2_detach().
+	 */
+	for (i = 0; i < 3; i++) {
+	    r = pipe(__daemon2_detach_pipe);
+	    if (r < 0)
+		    return -1;
+	    if (__daemon2_detach_pipe[1] <= STDERR_FILENO &&
+		(fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
+		    (void)dup2(fd, __daemon2_detach_pipe[0]);
+		    (void)dup2(fd, __daemon2_detach_pipe[1]);
+		    if (fd > STDERR_FILENO)
+			    (void)close(fd);
+		    continue;
+	    }
+	    break;
+	}
+
+	(void) fcntl(__daemon2_detach_pipe[1], F_SETNOSIGPIPE, 1);
+
+	r = fork();
+	if (r < 0) {
+		return -1;
+	} else if (r == 0) {
+		/* child */
+		close(__daemon2_detach_pipe[0]);
+		return 0;
+       }
+       /* Parent */
+
+       (void) close(__daemon2_detach_pipe[1]);
+
+       for (;;) {
+	       char dummy;
+	       r = read(__daemon2_detach_pipe[0], &dummy, 1);
+	       if (r < 0) {
+		       if (errno == EINTR)
+			       continue;
+		       _exit(1);
+	       } else if (r == 0) {
+		       _exit(1);
+	       } else { /* r > 0 */
+		       _exit(0);
+	       }
+       }
+}
+
+int
+daemon2_detach(int nochdir, int noclose)
+{
+	int r;
+	int fd;
+
+	if (setsid() == -1)
+		return -1;
+
+	if (!nochdir)
+		(void)chdir("/");
+
+	if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
+		(void)dup2(fd, STDIN_FILENO);
+		(void)dup2(fd, STDOUT_FILENO);
+		(void)dup2(fd, STDERR_FILENO);
+		if (fd > STDERR_FILENO)
+			(void)close(fd);
+	}
+
+	while (1) {
+		r = write(__daemon2_detach_pipe[1], "", 1);
+		if (r < 0) {
+			if (errno == EINTR)
+				continue;
+			else if (errno == EPIPE)
+				break;
+			else
+				return -1;
+		} else if (r == 0) {
+			/* Should not happen */
+			return -1;
+		} else {
+			break;
+		}
+	}
+
+	(void) close(__daemon2_detach_pipe[1]);
+
+	return 0;
+}
Index: src/libexec/rpc.rquotad/rquotad.c
===================================================================
RCS file: /bracket/repo/src/libexec/rpc.rquotad/rquotad.c,v
retrieving revision 1.32
diff -u -r1.32 rquotad.c
--- src/libexec/rpc.rquotad/rquotad.c	9 Jan 2012 15:37:34 -0000	1.32
+++ src/libexec/rpc.rquotad/rquotad.c	27 Jan 2014 14:41:29 -0000
@@ -62,13 +62,9 @@
 		from_inetd = 0;
 
 	if (!from_inetd) {
-		daemon(0, 0);
-
+		daemon2_fork();
 		(void) rpcb_unset(RQUOTAPROG, RQUOTAVERS, NULL);
 		(void) rpcb_unset(RQUOTAPROG, EXT_RQUOTAVERS, NULL);
-		(void) signal(SIGINT, cleanup);
-		(void) signal(SIGTERM, cleanup);
-		(void) signal(SIGHUP, cleanup);
 	}
 
 	openlog("rpc.rquotad", LOG_PID, LOG_DAEMON);
@@ -106,6 +102,13 @@
 		}
 	}
 
+	if (!from_inetd) {
+		daemon2_detach(0, 0);
+		(void) signal(SIGINT, cleanup);
+		(void) signal(SIGTERM, cleanup);
+		(void) signal(SIGHUP, cleanup);
+	}
+
 	svc_run();
 	syslog(LOG_ERR, "svc_run returned");
 	exit(1);
Index: src/tests/lib/libc/gen/Makefile
===================================================================
RCS file: /bracket/repo/src/tests/lib/libc/gen/Makefile,v
retrieving revision 1.38
diff -u -r1.38 Makefile
--- src/tests/lib/libc/gen/Makefile	8 Nov 2012 03:13:47 -0000	1.38
+++ src/tests/lib/libc/gen/Makefile	27 Jan 2014 14:41:29 -0000
@@ -1,5 +1,7 @@
 # $NetBSD: Makefile,v 1.38 2012/11/08 03:13:47 pgoyette Exp $
 
+NOMAN=		# defined
+
 .include <bsd.own.mk>
 
 TESTSDIR=	${TESTSBASE}/lib/libc/gen
@@ -11,6 +13,7 @@
 TESTS_C+=	t_basedirname
 TESTS_C+=	t_closefrom
 TESTS_C+=	t_cpuset
+TESTS_C+=	t_daemon2
 TESTS_C+=	t_dir
 TESTS_C+=	t_fmtcheck
 TESTS_C+=	t_fnmatch
@@ -47,4 +50,9 @@
 LDADD.t_syslog+=	-lpthread
 DPADD.t_syslog+=	${LIBPTHREAD}
 
+BINDIR=		${TESTSDIR}
+PROGS=		h_daemon2
+
+CLEANFILES+=	h_daemon2
+
 .include <bsd.test.mk>
Index: src/tests/lib/libc/gen/h_daemon2.c
===================================================================
RCS file: src/tests/lib/libc/gen/h_daemon2.c
diff -N src/tests/lib/libc/gen/h_daemon2.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/tests/lib/libc/gen/h_daemon2.c	28 Jan 2014 10:09:27 -0000
@@ -0,0 +1,72 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (c) 2013 The NetBSD Foundation, Inc.
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/*
+ * Daemon to test daemon2_fork() and daemon2_detach().
+ */
+
+#include <sys/cdefs.h>
+__COPYRIGHT("@(#) Copyright (c) 2013\
+ The NetBSD Foundation, inc. All rights reserved.");
+__RCSID("$NetBSD$");
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+int
+main(int argc, char *argv[])
+{
+	int r;
+	FILE *f;
+
+	if (argc != 2) {
+		fprintf(stderr, "usage: h_daemon2 succeed | fail");
+		exit(1);
+	}
+	r = daemon2_fork();
+	assert(r == 0);
+	/* Emulate slow initialization */
+	(void) sleep(1);
+	f = fopen("daemon.pid", "w");
+	assert(f != NULL);
+	r = fprintf(f, "%d\n", (int) getpid());
+	assert(r > 0);
+	r = fclose(f);
+	assert(r == 0);
+        r = fprintf(stderr, "message\n");
+	assert(r > 0);
+	if (strcmp(argv[1], "succeed") != 0)
+		exit(1);
+ 	r = daemon2_detach(0, 0);
+	assert(r == 0);
+	for (;;)
+		(void) sleep(1);
+}
Index: src/tests/lib/libc/gen/t_daemon2.c
===================================================================
RCS file: src/tests/lib/libc/gen/t_daemon2.c
diff -N src/tests/lib/libc/gen/t_daemon2.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/tests/lib/libc/gen/t_daemon2.c	27 Jan 2014 14:41:29 -0000
@@ -0,0 +1,127 @@
+/*	$NetBSD$ */
+
+/*-
+ * Copyright (c) 2013 The NetBSD Foundation, Inc.
+ * 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 COPYRIGHT HOLDERS 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
+ * COPYRIGHT HOLDERS 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/types.h>
+#include <sys/wait.h>
+
+#include <atf-c.h>
+#include <err.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static void
+test_daemon2_detach(const char *srcdir, int succeed)
+{
+	int stderr_pipe[2];
+	pid_t pid, sid;
+	int status;
+	int r;
+	r = pipe(stderr_pipe);
+	if (r < 0)
+		err(1, "pipe");
+	pid = fork();
+	if (pid < 0)
+		err(1, "fork");
+	if (pid == 0) {
+		char fnbuf[FILENAME_MAX];
+		r = close(stderr_pipe[0]);
+		ATF_CHECK(r == 0);
+		r = dup2(stderr_pipe[1], 2);
+		if (r < 0)
+			err(1, "dup2");
+		/* Child.  Start the daemon. */
+		snprintf(fnbuf, sizeof fnbuf, "%s/h_daemon2", srcdir);
+		r = execl(fnbuf, "h_daemon2", succeed ? "succeed" : "fail", (char *) 0);
+		if (r < 0)
+			err(1, "exec");
+	} else if (pid > 0) {
+		/* Parent */
+		char buf[80];
+		r = close(stderr_pipe[1]);
+		ATF_CHECK(r == 0);
+		pid_t wpid = wait(&status);
+		ATF_CHECK_EQ(wpid, pid);
+		r = read(stderr_pipe[0], buf, sizeof buf);
+		ATF_CHECK_EQ(r, sizeof("message\n") - 1);
+		r = memcmp(buf, "message\n", sizeof("message\n") - 1);
+		ATF_CHECK_EQ(r, 0);
+		if (succeed) {
+			int rpid;
+			FILE *f;
+			ATF_CHECK_EQ(status, 0);
+			f = fopen("daemon.pid", "r");
+			ATF_CHECK(f != NULL);
+			r = fscanf(f, "%d", &rpid);
+			ATF_CHECK_EQ(r, 1);
+			sid = getsid(rpid);
+			ATF_CHECK_EQ(sid, rpid);
+			r = kill(rpid, SIGTERM);
+			ATF_CHECK_EQ(r, 0);
+		} else {
+			ATF_CHECK_EQ(WEXITSTATUS(status), 1);
+		}
+	}
+}
+
+ATF_TC(daemon2_success);
+ATF_TC_HEAD(daemon2_success, tc)
+{
+	atf_tc_set_md_var(tc, "descr", "Test successful "
+	    "daemon2_fork() and daemon2_detach()");
+}
+
+ATF_TC_BODY(daemon2_success, tc)
+{
+	const char *srcdir = atf_tc_get_config_var(tc, "srcdir");
+        test_daemon2_detach(srcdir, 1);
+}
+
+ATF_TC(daemon2_failure);
+ATF_TC_HEAD(daemon2_failure, tc)
+{
+	atf_tc_set_md_var(tc, "descr", "Test daemon failing "
+	    "between daemon2_fork() and daemon2_detach()");
+}
+
+ATF_TC_BODY(daemon2_failure, tc)
+{
+	const char *srcdir = atf_tc_get_config_var(tc, "srcdir");	
+	test_daemon2_detach(srcdir, 0);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+	ATF_TP_ADD_TC(tp, daemon2_success);
+	ATF_TP_ADD_TC(tp, daemon2_failure);
+
+	return atf_no_error();
+}
Index: src/tests/lib/libc/net/h_dns_server.c
===================================================================
RCS file: /bracket/repo/src/tests/lib/libc/net/h_dns_server.c,v
retrieving revision 1.3
diff -u -r1.3 h_dns_server.c
--- src/tests/lib/libc/net/h_dns_server.c	9 Jan 2014 02:18:10 -0000	1.3
+++ src/tests/lib/libc/net/h_dns_server.c	27 Jan 2014 14:44:28 -0000
@@ -165,104 +165,6 @@
 }
 #endif
 
-/* XXX the daemon2_* functions should be in a library */
-
-int __daemon2_detach_pipe[2];
-
-static int
-daemon2_fork(void)
-{
-	int r;
-	int fd;
-	int i;
-
-	/*
-	 * Set up the pipe, making sure the write end does not
-	 * get allocated one of the file descriptors that will
-	 * be closed in daemon2_detach().
-	 */
-	for (i = 0; i < 3; i++) {
-	    r = pipe(__daemon2_detach_pipe);
-	    if (r < 0)
-		    return -1;
-	    if (__daemon2_detach_pipe[1] <= STDERR_FILENO &&
-		(fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
-		    (void)dup2(fd, __daemon2_detach_pipe[0]);
-		    (void)dup2(fd, __daemon2_detach_pipe[1]);
-		    if (fd > STDERR_FILENO)
-			    (void)close(fd);
-		    continue;
-	    }
-	    break;
-	}
-
-	r = fork();
-	if (r < 0) {
-		return -1;
-	} else if (r == 0) {
-		/* child */
-		close(__daemon2_detach_pipe[0]);
-		return 0;
-       }
-       /* Parent */
-
-       (void) close(__daemon2_detach_pipe[1]);
-
-       for (;;) {
-	       char dummy;
-	       r = read(__daemon2_detach_pipe[0], &dummy, 1);
-	       if (r < 0) {
-		       if (errno == EINTR)
-			       continue;
-		       _exit(1);
-	       } else if (r == 0) {
-		       _exit(1);
-	       } else { /* r > 0 */
-		       _exit(0);
-	       }
-       }
-}
-
-static int
-daemon2_detach(int nochdir, int noclose)
-{
-	int r;
-	int fd;
-
-	if (setsid() == -1)
-		return -1;
-
-	if (!nochdir)
-		(void)chdir("/");
-
-	if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
-		(void)dup2(fd, STDIN_FILENO);
-		(void)dup2(fd, STDOUT_FILENO);
-		(void)dup2(fd, STDERR_FILENO);
-		if (fd > STDERR_FILENO)
-			(void)close(fd);
-	}
-
-	while (1) {
-		r = write(__daemon2_detach_pipe[1], "", 1);
-		if (r < 0) {
-			if (errno == EINTR)
-				continue;
-			/* May get "broken pipe" here if parent is killed */
-			return -1;
-		} else if (r == 0) {
-			/* Should not happen */
-			return -1;
-		} else {
-			break;
-		}
-	}
-
-	(void) close(__daemon2_detach_pipe[1]);
-
-	return 0;
-}
-
 int main(int argc, char **argv) {
 	int s, r, protocol;
 	union sockaddr_either saddr;
Index: src/usr.sbin/nfsd/nfsd.c
===================================================================
RCS file: /bracket/repo/src/usr.sbin/nfsd/nfsd.c,v
retrieving revision 1.61
diff -u -r1.61 nfsd.c
--- src/usr.sbin/nfsd/nfsd.c	15 Aug 2012 00:16:06 -0000	1.61
+++ src/usr.sbin/nfsd/nfsd.c	27 Jan 2014 14:41:29 -0000
@@ -347,13 +347,8 @@
 			ip4flag = 1;
 	}
 
-	if (debug == 0) {
-		daemon(0, 0);
-		(void)signal(SIGHUP, SIG_IGN);
-		(void)signal(SIGINT, SIG_IGN);
-		(void)signal(SIGQUIT, SIG_IGN);
-		(void)signal(SIGSYS, nonfs);
-	}
+	if (debug == 0)
+		daemon2_fork();
 
 	openlog("nfsd", LOG_PID, LOG_DAEMON);
 
@@ -401,6 +396,14 @@
 
 	pthread_setname_np(pthread_self(), "master", NULL);
 
+	if (debug == 0) {
+		daemon2_detach(0, 0);
+		(void)signal(SIGHUP, SIG_IGN);
+		(void)signal(SIGINT, SIG_IGN);
+		(void)signal(SIGQUIT, SIG_IGN);
+		(void)signal(SIGSYS, nonfs);
+	}
+
 	/*
 	 * Loop forever accepting connections and passing the sockets
 	 * into the kernel for the mounts.
