svn commit: r273936 - head/contrib/netbsd-tests/lib/libc/net

Garrett Cooper ngie at FreeBSD.org
Sat Nov 1 17:14:30 UTC 2014


Author: ngie
Date: Sat Nov  1 17:14:29 2014
New Revision: 273936
URL: https://svnweb.freebsd.org/changeset/base/273936

Log:
  Port lib/libc/net/h_dns_server to FreeBSD
  
  Submitted by: pho

Modified:
  head/contrib/netbsd-tests/lib/libc/net/h_dns_server.c

Modified: head/contrib/netbsd-tests/lib/libc/net/h_dns_server.c
==============================================================================
--- head/contrib/netbsd-tests/lib/libc/net/h_dns_server.c	Sat Nov  1 17:13:13 2014	(r273935)
+++ head/contrib/netbsd-tests/lib/libc/net/h_dns_server.c	Sat Nov  1 17:14:29 2014	(r273936)
@@ -49,7 +49,13 @@ __RCSID("$NetBSD: h_dns_server.c,v 1.4 2
 #include <sys/socket.h>
 
 #include <netinet/in.h>
+#ifdef __NetBSD__
 #include <netinet6/in6.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <paths.h>
+#endif
 
 union sockaddr_either {
 	struct sockaddr s;
@@ -164,6 +170,106 @@ name2str(const void *v, char *buf, size_
 }
 #endif
 
+#ifdef __FreeBSD__
+/* 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;
+}
+#endif
+
 int main(int argc, char **argv) {
 	int s, r, protocol;
 	union sockaddr_either saddr;
@@ -176,6 +282,9 @@ int main(int argc, char **argv) {
 	char buf1[1024], buf2[1024];
 #endif
 
+#ifdef __FreeBSD__
+	daemon2_fork();
+#endif
 	if (argc < 2 || ((protocol = argv[1][0]) != '4' && protocol != '6'))
 		errx(1, "usage: dns_server 4 | 6");
 	s = socket(protocol == '4' ? PF_INET : PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
@@ -212,11 +321,19 @@ int main(int argc, char **argv) {
 	f = fopen(pidfile_name, "w");
 	fprintf(f, "%d", getpid());
 	fclose(f);
+#ifdef __FreeBSD__
+#ifdef DEBUG
+	daemon2_detach(0, 1);
+#else
+	daemon2_detach(0, 0);
+#endif
+#else
 #ifdef DEBUG
 	daemon(0, 1);
 #else
 	daemon(0, 0);
 #endif
+#endif
 
 	for (;;) {
 		unsigned char buf[512];


More information about the svn-src-head mailing list