--- a/inetd.8
+++ b/inetd.8
@@ -42,11 +42,7 @@
 .Op Ar configuration_file
 .Sh DESCRIPTION
 .Nm inetd
-should be run at boot time by
-.Pa /etc/rc
-(see
-.Xr rc 8 ) .
-It then listens for connections on certain internet sockets.
+listens for connections on certain internet sockets.
 When a connection is found on one
 of its sockets, it decides what service the socket
 corresponds to, and invokes a program to service the request.
@@ -149,7 +145,8 @@ The
 .Em service name
 entry is the name of a valid service in
 the file
-.Pa /etc/services .
+.Pa /etc/services
+or a port number.
 For
 .Dq internal
 services (discussed below), the service
@@ -166,7 +163,7 @@ The part on the right of the
 is the RPC version number.
 This can simply be a single numeric argument or a range of versions.
 A range is bounded by the low version to the high version -
-.Dq rusers/1-3 .
+.Dq rusers/1\-3 .
 For
 .Ux Ns -domain
 sockets this field specifies the path name of the socket.
@@ -186,7 +183,8 @@ reliably delivered message, or sequenced
 The
 .Em protocol
 must be a valid protocol as given in
-.Pa /etc/protocols .
+.Pa /etc/protocols or
+.Dq unix .
 Examples might be
 .Dq tcp
 or
@@ -377,9 +375,7 @@ If you have only one server on
 only IPv6 traffic will be routed to the server.
 .El
 .Sh SEE ALSO
-.Xr comsat 8 ,
 .Xr fingerd 8 ,
-.Xr ftp-proxy 8 ,
 .Xr ftpd 8 ,
 .Xr identd 8 ,
 .Xr rshd 8 ,
@@ -394,7 +390,23 @@ Support for Sun-RPC
 based services is modelled after that
 provided by SunOS 4.1.
 IPv6 support was added by the KAME project in 1999.
+.Pp
+Marco d'Itri ported this code from OpenBSD in summer 2002 and added
+socket buffers tuning and libwrap support from the NetBSD source tree.
 .Sh BUGS
+On Linux systems, the daemon cannot reload its configuration and needs
+to be restarted when the host address for a service is changed between
+.Dq \&*
+and a specific address.
+.Pp
+Server programs used with
+.Dq dgram
+.Dq udp
+.Dq nowait
+must read from the network socket, or
+.Nm inetd
+will spawn processes until the maximum is reached.
+.Pp
 Host address specifiers, while they make conceptual sense for RPC
 services, do not work entirely correctly.
 This is largely because the
--- a/inetd.c
+++ b/inetd.c
@@ -128,6 +128,7 @@
 #include <sys/un.h>
 #include <sys/file.h>
 #include <sys/wait.h>
+#include <time.h>
 #include <sys/time.h>
 #include <sys/resource.h>
 
@@ -146,13 +147,18 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
+#ifdef HAVE_SETUSERCONTEXT
 #include <login_cap.h>
+#endif
+#ifdef HAVE_GETIFADDRS
 #include <ifaddrs.h>
+#endif
 #include <rpc/rpc.h>
 #include <rpc/pmap_clnt.h>
-#include <rpcsvc/nfs_prot.h>
 #include "pathnames.h"
 
+size_t strlcpy(char *, const char *, size_t);
+
 #define	TOOMANY		256		/* don't start more than TOOMANY */
 #define	CNT_INTVL	60		/* servers in CNT_INTVL sec. */
 #define	RETRYTIME	(60*10)		/* retry after bind or server fail */
@@ -325,7 +331,6 @@ main(int argc, char *argv[])
 		switch (ch) {
 		case 'd':
 			debug = 1;
-			options |= SO_DEBUG;
 			break;
 		case 'R': {	/* invocation rate */
 			char *p;
@@ -367,9 +372,13 @@ main(int argc, char *argv[])
 	umask(022);
 	if (debug == 0) {
 		daemon(0, 0);
+#ifdef HAVE_SETLOGIN
 		if (uid == 0)
 			(void) setlogin("");
+#endif
 	}
+	if (debug && uid == 0)
+		options |= SO_DEBUG;
 
 	if (uid == 0) {
 		gid_t gid = getgid();
@@ -414,6 +423,15 @@ main(int argc, char *argv[])
 	sa.sa_handler = SIG_IGN;
 	sigaction(SIGPIPE, &sa, &sapipe);
 
+	/* space for daemons to overwrite environment for ps */
+	{
+#define DUMMYSIZE 100
+		char dummy[DUMMYSIZE];
+		memset(dummy, 'x', DUMMYSIZE - 1);
+		dummy[DUMMYSIZE - 1] = '\0';
+		setenv("inetd_dummy", dummy, 1);
+	}
+
 	for (;;) {
 		int n, ctrl = -1;
 
@@ -569,9 +587,6 @@ dg_badinput(struct sockaddr *sa)
 		return 0;
 	}
 
-	if (port < IPPORT_RESERVED || port == NFS_PORT)
-		goto bad;
-
 	return (0);
 
 bad:
@@ -581,6 +596,7 @@ bad:
 int
 dg_broadcast(struct in_addr *in)
 {
+#ifdef HAVE_GETIFADDRS
 	struct ifaddrs *ifa, *ifap;
 	struct sockaddr_in *sin;
 
@@ -597,6 +613,7 @@ dg_broadcast(struct in_addr *in)
 		}
 	}
 	freeifaddrs(ifap);
+#endif
 	return (0);
 }
 
@@ -1843,7 +1860,7 @@ print_service(char *action, struct servt
 	fprintf(stderr,
 	    " wait.max=%hd.%d user:group=%s:%s builtin=%lx server=%s\n",
 	    sep->se_wait, sep->se_max, sep->se_user,
-	    sep->se_group ? sep->se_group : "wheel",
+	    sep->se_group ? sep->se_group : "(default)",
 	    (long)sep->se_bi, sep->se_server);
 }
 
@@ -1951,6 +1968,7 @@ spawn(struct servtab *sep, int ctrl)
 				if (uid != pwd->pw_uid)
 					exit(1);
 			} else {
+#ifdef HAVE_SETUSERCONTEXT
 				tmpint = LOGIN_SETALL &
 				    ~(LOGIN_SETGROUP|LOGIN_SETLOGIN);
 				if (pwd->pw_uid)
@@ -1966,6 +1984,53 @@ spawn(struct servtab *sep, int ctrl)
 					    sep->se_service, sep->se_proto);
 					exit(1);
 				}
+#else
+				/* what about setpriority(2), setrlimit(2),
+				 * and umask(2)? The $PATH is cleared.
+				 */
+				if (pwd->pw_uid) {
+				    if (sep->se_group)
+					pwd->pw_gid = grp->gr_gid;
+				    if (setgid(pwd->pw_gid) < 0) {
+					syslog(LOG_ERR,
+					    "%s/%s: can't set gid %d: %m",
+					    sep->se_service, sep->se_proto,
+					    pwd->pw_gid);
+					exit(1);
+				    }
+				    if (initgroups(pwd->pw_name, pwd->pw_gid)
+					    < 0) {
+					syslog(LOG_ERR,
+					    "%s/%s: can't initgroups(%s): %m",
+					    sep->se_service, sep->se_proto,
+					    pwd->pw_name);
+					exit(1);
+				    }
+				    if (setuid(pwd->pw_uid) < 0) {
+					syslog(LOG_ERR,
+						"%s/%s: can't set uid %d: %m",
+						sep->se_service, sep->se_proto,
+						pwd->pw_uid);
+					exit(1);
+				    }
+				} else if (sep->se_group) {
+				    if (setgid(pwd->pw_gid) < 0) {
+					syslog(LOG_ERR,
+					    "%s/%s: can't set gid %d: %m",
+					    sep->se_service, sep->se_proto,
+					    pwd->pw_gid);
+					exit(1);
+				    }
+				    if (initgroups(pwd->pw_name, pwd->pw_gid)
+					    < 0) {
+					syslog(LOG_ERR,
+					    "%s/%s: can't initgroups(%s): %m",
+					    sep->se_service, sep->se_proto,
+					    pwd->pw_name);
+					exit(1);
+				    }
+				}
+#endif
 			}
 			if (debug)
 				fprintf(stderr, "%ld execv %s\n",
--- /dev/null
+++ b/strlcpy.c
@@ -0,0 +1,63 @@
+/*	$OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp $	*/
+
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ * 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. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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.
+ *
+ * (Old style prototype traslated)
+ */
+
+#include <sys/types.h>
+#include <string.h>
+
+/*
+ * Copy src to string dst of size siz.  At most siz-1 characters
+ * will be copied.  Always NUL terminates (unless siz == 0).
+ * Returns strlen(src); if retval >= siz, truncation occurred.
+ */
+size_t strlcpy(char *dst, const char *src, size_t siz)
+{
+	register char *d = dst;
+	register const char *s = src;
+	register size_t n = siz;
+
+	/* Copy as many bytes as will fit */
+	if (n != 0 && --n != 0) {
+		do {
+			if ((*d++ = *s++) == 0)
+				break;
+		} while (--n != 0);
+	}
+
+	/* Not enough room in dst, add NUL and traverse rest of src */
+	if (n == 0) {
+		if (siz != 0)
+			*d = '\0';		/* NUL-terminate dst */
+		while (*s++)
+			;
+	}
+
+	return(s - src - 1);	/* count does not include NUL */
+}
--- /dev/null
+++ b/bsd-closefrom.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2004-2005 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#define HAVE_FCNTL_H
+#define HAVE_DIRENT_H
+#ifdef linux
+#define HAVE_DIRFD
+#define HAVE_PROC_PID
+#endif
+#define HAVE_SYSCONF
+
+#ifndef HAVE_CLOSEFROM
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <unistd.h>
+#include <stdio.h>
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+#include <limits.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef HAVE_DIRENT_H
+# include <dirent.h>
+# define NAMLEN(dirent) strlen((dirent)->d_name)
+#else
+# define dirent direct
+# define NAMLEN(dirent) (dirent)->d_namlen
+# ifdef HAVE_SYS_NDIR_H
+#  include <sys/ndir.h>
+# endif
+# ifdef HAVE_SYS_DIR_H
+#  include <sys/dir.h>
+# endif
+# ifdef HAVE_NDIR_H
+#  include <ndir.h>
+# endif
+#endif
+
+#ifndef OPEN_MAX
+# define OPEN_MAX	256
+#endif
+
+#if 0
+__unused static const char rcsid[] = "$Sudo: closefrom.c,v 1.11 2006/08/17 15:26:54 millert Exp $";
+#endif /* lint */
+
+/*
+ * Close all file descriptors greater than or equal to lowfd.
+ */
+#ifdef HAVE_FCNTL_CLOSEM
+void
+closefrom(int lowfd)
+{
+    (void) fcntl(lowfd, F_CLOSEM, 0);
+}
+#else
+void
+closefrom(int lowfd)
+{
+    long fd, maxfd;
+#if defined(HAVE_DIRFD) && defined(HAVE_PROC_PID)
+    char fdpath[PATH_MAX], *endp;
+    struct dirent *dent;
+    DIR *dirp;
+    int len;
+
+    /* Check for a /proc/$$/fd directory. */
+    len = snprintf(fdpath, sizeof(fdpath), "/proc/%ld/fd", (long)getpid());
+    if (len > 0 && (size_t)len <= sizeof(fdpath) && (dirp = opendir(fdpath))) {
+	while ((dent = readdir(dirp)) != NULL) {
+	    fd = strtol(dent->d_name, &endp, 10);
+	    if (dent->d_name != endp && *endp == '\0' &&
+		fd >= 0 && fd < INT_MAX && fd >= lowfd && fd != dirfd(dirp))
+		(void) close((int) fd);
+	}
+	(void) closedir(dirp);
+    } else
+#endif
+    {
+	/*
+	 * Fall back on sysconf() or getdtablesize().  We avoid checking
+	 * resource limits since it is possible to open a file descriptor
+	 * and then drop the rlimit such that it is below the open fd.
+	 */
+#ifdef HAVE_SYSCONF
+	maxfd = sysconf(_SC_OPEN_MAX);
+#else
+	maxfd = getdtablesize();
+#endif /* HAVE_SYSCONF */
+	if (maxfd < 0)
+	    maxfd = OPEN_MAX;
+
+	for (fd = lowfd; fd < maxfd; fd++)
+	    (void) close((int) fd);
+    }
+}
+#endif /* !HAVE_FCNTL_CLOSEM */
+#endif /* HAVE_CLOSEFROM */
