--- ntpd/ntpd.c.orig
+++ ntpd/ntpd.c
@@ -182,7 +182,6 @@ char *group;		/* group to switch to */
 const char *chrootdir;	/* directory to chroot to */
 uid_t sw_uid;
 gid_t sw_gid;
-char *endp;
 struct group *gr;
 struct passwd *pw;
 #endif /* HAVE_DROPROOT */
@@ -518,6 +517,217 @@ set_process_priority(void)
 }
 #endif	/* !SIM */
 
+#ifndef SIM
+/*
+ * Detach from terminal (much like daemon())
+ * Nothe that this function calls exit()
+ */
+static void
+detach_from_terminal(
+	int pipe_fds[2],
+	long wait_sync,
+	const char *logfilename
+	)
+{
+	int rc;
+	int exit_code;
+#  if !defined(HAVE_SETSID) && !defined (HAVE_SETPGID) && defined(TIOCNOTTY)
+	int		fid;
+#  endif
+#  ifdef _AIX
+	struct sigaction sa;
+#  endif
+
+	rc = fork();
+	if (-1 == rc) {
+		exit_code = (errno) ? errno : -1;
+		msyslog(LOG_ERR, "fork: %m");
+		exit(exit_code);
+	}
+	if (rc > 0) {
+		/* parent */
+		exit_code = wait_child_sync_if(pipe_fds[0],
+					       wait_sync);
+		exit(exit_code);
+	}
+
+	/*
+	 * child/daemon
+	 * close all open files excepting waitsync_fd_to_close.
+	 * msyslog() unreliable until after init_logging().
+	 */
+	closelog();
+	if (syslog_file != NULL) {
+		fclose(syslog_file);
+		syslog_file = NULL;
+		syslogit = TRUE;
+	}
+	close_all_except(waitsync_fd_to_close);
+	INSIST(0 == open("/dev/null", 0) && 1 == dup2(0, 1) \
+		&& 2 == dup2(0, 2));
+
+	init_logging(progname, 0, TRUE);
+	/* we lost our logfile (if any) daemonizing */
+	setup_logfile(logfilename);
+
+#  ifdef SYS_DOMAINOS
+	{
+		uid_$t puid;
+		status_$t st;
+
+		proc2_$who_am_i(&puid);
+		proc2_$make_server(&puid, &st);
+	}
+#  endif	/* SYS_DOMAINOS */
+#  ifdef HAVE_SETSID
+	if (setsid() == (pid_t)-1)
+		msyslog(LOG_ERR, "setsid(): %m");
+#  elif defined(HAVE_SETPGID)
+	if (setpgid(0, 0) == -1)
+		msyslog(LOG_ERR, "setpgid(): %m");
+#  else		/* !HAVE_SETSID && !HAVE_SETPGID follows */
+#   ifdef TIOCNOTTY
+	fid = open("/dev/tty", 2);
+	if (fid >= 0) {
+		ioctl(fid, (u_long)TIOCNOTTY, NULL);
+		close(fid);
+	}
+#   endif	/* TIOCNOTTY */
+	ntp_setpgrp(0, getpid());
+#  endif	/* !HAVE_SETSID && !HAVE_SETPGID */
+#  ifdef _AIX
+	/* Don't get killed by low-on-memory signal. */
+	sa.sa_handler = catch_danger;
+	sigemptyset(&sa.sa_mask);
+	sa.sa_flags = SA_RESTART;
+	sigaction(SIGDANGER, &sa, NULL);
+#  endif	/* _AIX */
+
+	return;
+}
+
+/*
+ * Map user name/number to user ID
+*/
+static int
+map_user(
+	)
+{
+	char *endp;
+
+	if (isdigit((unsigned char)*user)) {
+		sw_uid = (uid_t)strtoul(user, &endp, 0);
+		if (*endp != '\0')
+			goto getuser;
+
+		if ((pw = getpwuid(sw_uid)) != NULL) {
+			free(user);
+			user = estrdup(pw->pw_name);
+			sw_gid = pw->pw_gid;
+		} else {
+			errno = 0;
+			msyslog(LOG_ERR, "Cannot find user ID %s", user);
+			return 0;
+		}
+
+	} else {
+getuser:
+		errno = 0;
+		if ((pw = getpwnam(user)) != NULL) {
+			sw_uid = pw->pw_uid;
+			sw_gid = pw->pw_gid;
+		} else {
+			if (errno)
+				msyslog(LOG_ERR, "getpwnam(%s) failed: %m", user);
+			else
+				msyslog(LOG_ERR, "Cannot find user `%s'", user);
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
+/*
+ * Map group name/number to group ID
+*/
+static int
+map_group(
+	)
+{
+	char *endp;
+
+	if (isdigit((unsigned char)*group)) {
+		sw_gid = (gid_t)strtoul(group, &endp, 0);
+		if (*endp != '\0')
+			goto getgroup;
+	} else {
+getgroup:
+		if ((gr = getgrnam(group)) != NULL) {
+			sw_gid = gr->gr_gid;
+		} else {
+			errno = 0;
+			msyslog(LOG_ERR, "Cannot find group `%s'", group);
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
+/*
+ * Change (effective) user and group IDs, also initialize the supplementary group access list
+ */
+int
+set_user_group_ids(
+	)
+{
+	/* If the the user was already mapped, no need to map it again */
+	if ((NULL != user) && (0 == sw_uid)) {
+		if (0 == map_user())
+			exit (-1);
+	}
+	/* same applies for the group */
+	if ((NULL != group) && (0 == sw_gid)) {
+		if (0 == map_group())
+			exit (-1);
+	}
+
+	if (user && initgroups(user, sw_gid)) {
+		msyslog(LOG_ERR, "Cannot initgroups() to user `%s': %m", user);
+		return 0;
+	}
+	if (group && setgid(sw_gid)) {
+		msyslog(LOG_ERR, "Cannot setgid() to group `%s': %m", group);
+		return 0;
+	}
+	if (group && setegid(sw_gid)) {
+		msyslog(LOG_ERR, "Cannot setegid() to group `%s': %m", group);
+		return 0;
+	}
+	if (group) {
+		if (0 != setgroups(1, &sw_gid)) {
+			msyslog(LOG_ERR, "setgroups(1, %d) failed: %m", sw_gid);
+			return 0;
+		}
+	}
+	else if (pw)
+		if (0 != initgroups(pw->pw_name, pw->pw_gid)) {
+			msyslog(LOG_ERR, "initgroups(<%s>, %d) filed: %m", pw->pw_name, pw->pw_gid);
+			return 0;
+		}
+	if (user && setuid(sw_uid)) {
+		msyslog(LOG_ERR, "Cannot setuid() to user `%s': %m", user);
+		return 0;
+	}
+	if (user && seteuid(sw_uid)) {
+		msyslog(LOG_ERR, "Cannot seteuid() to user `%s': %m", user);
+		return 0;
+	}
+
+	return 1;
+}
+#endif /* !SIM */
 
 /*
  * Main program.  Initialize us, disconnect us from the tty if necessary,
@@ -544,12 +754,6 @@ ntpdmain(
 	int		pipe_fds[2];
 	int		rc;
 	int		exit_code;
-#  ifdef _AIX
-	struct sigaction sa;
-#  endif
-#  if !defined(HAVE_SETSID) && !defined (HAVE_SETPGID) && defined(TIOCNOTTY)
-	int		fid;
-#  endif
 # endif	/* HAVE_WORKING_FORK*/
 # ifdef SCO5_CLOCK
 	int		fd;
@@ -732,70 +936,7 @@ ntpdmain(
 	if (!nofork) {
 
 # ifdef HAVE_WORKING_FORK
-		rc = fork();
-		if (-1 == rc) {
-			exit_code = (errno) ? errno : -1;
-			msyslog(LOG_ERR, "fork: %m");
-			exit(exit_code);
-		}
-		if (rc > 0) {	
-			/* parent */
-			exit_code = wait_child_sync_if(pipe_fds[0],
-						       wait_sync);
-			exit(exit_code);
-		}
-		
-		/*
-		 * child/daemon 
-		 * close all open files excepting waitsync_fd_to_close.
-		 * msyslog() unreliable until after init_logging().
-		 */
-		closelog();
-		if (syslog_file != NULL) {
-			fclose(syslog_file);
-			syslog_file = NULL;
-			syslogit = TRUE;
-		}
-		close_all_except(waitsync_fd_to_close);
-		INSIST(0 == open("/dev/null", 0) && 1 == dup2(0, 1) \
-			&& 2 == dup2(0, 2));
-
-		init_logging(progname, 0, TRUE);
-		/* we lost our logfile (if any) daemonizing */
-		setup_logfile(logfilename);
-
-#  ifdef SYS_DOMAINOS
-		{
-			uid_$t puid;
-			status_$t st;
-
-			proc2_$who_am_i(&puid);
-			proc2_$make_server(&puid, &st);
-		}
-#  endif	/* SYS_DOMAINOS */
-#  ifdef HAVE_SETSID
-		if (setsid() == (pid_t)-1)
-			msyslog(LOG_ERR, "setsid(): %m");
-#  elif defined(HAVE_SETPGID)
-		if (setpgid(0, 0) == -1)
-			msyslog(LOG_ERR, "setpgid(): %m");
-#  else		/* !HAVE_SETSID && !HAVE_SETPGID follows */
-#   ifdef TIOCNOTTY
-		fid = open("/dev/tty", 2);
-		if (fid >= 0) {
-			ioctl(fid, (u_long)TIOCNOTTY, NULL);
-			close(fid);
-		}
-#   endif	/* TIOCNOTTY */
-		ntp_setpgrp(0, getpid());
-#  endif	/* !HAVE_SETSID && !HAVE_SETPGID */
-#  ifdef _AIX
-		/* Don't get killed by low-on-memory signal. */
-		sa.sa_handler = catch_danger;
-		sigemptyset(&sa.sa_mask);
-		sa.sa_flags = SA_RESTART;
-		sigaction(SIGDANGER, &sa, NULL);
-#  endif	/* _AIX */
+		detach_from_terminal(pipe_fds, wait_sync, logfilename);
 # endif		/* HAVE_WORKING_FORK */
 	}
 
@@ -968,51 +1109,12 @@ ntpdmain(
 #  endif	/* HAVE_LINUX_CAPABILITIES || HAVE_SOLARIS_PRIVS */
 
 		if (user != NULL) {
-			if (isdigit((unsigned char)*user)) {
-				sw_uid = (uid_t)strtoul(user, &endp, 0);
-				if (*endp != '\0')
-					goto getuser;
-
-				if ((pw = getpwuid(sw_uid)) != NULL) {
-					free(user);
-					user = estrdup(pw->pw_name);
-					sw_gid = pw->pw_gid;
-				} else {
-					errno = 0;
-					msyslog(LOG_ERR, "Cannot find user ID %s", user);
-					exit (-1);
-				}
-
-			} else {
-getuser:
-				errno = 0;
-				if ((pw = getpwnam(user)) != NULL) {
-					sw_uid = pw->pw_uid;
-					sw_gid = pw->pw_gid;
-				} else {
-					if (errno)
-						msyslog(LOG_ERR, "getpwnam(%s) failed: %m", user);
-					else
-						msyslog(LOG_ERR, "Cannot find user `%s'", user);
-					exit (-1);
-				}
-			}
+			if (0 == map_user())
+				exit (-1);
 		}
 		if (group != NULL) {
-			if (isdigit((unsigned char)*group)) {
-				sw_gid = (gid_t)strtoul(group, &endp, 0);
-				if (*endp != '\0')
-					goto getgroup;
-			} else {
-getgroup:
-				if ((gr = getgrnam(group)) != NULL) {
-					sw_gid = gr->gr_gid;
-				} else {
-					errno = 0;
-					msyslog(LOG_ERR, "Cannot find group `%s'", group);
-					exit (-1);
-				}
-			}
+			if (0 == map_group())
+				exit (-1);
 		}
 
 		if (chrootdir ) {
@@ -1046,37 +1148,8 @@ getgroup:
 			exit(-1);
 		}
 #  endif /* HAVE_SOLARIS_PRIVS */
-		if (user && initgroups(user, sw_gid)) {
-			msyslog(LOG_ERR, "Cannot initgroups() to user `%s': %m", user);
-			exit (-1);
-		}
-		if (group && setgid(sw_gid)) {
-			msyslog(LOG_ERR, "Cannot setgid() to group `%s': %m", group);
-			exit (-1);
-		}
-		if (group && setegid(sw_gid)) {
-			msyslog(LOG_ERR, "Cannot setegid() to group `%s': %m", group);
-			exit (-1);
-		}
-		if (group) {
-			if (0 != setgroups(1, &sw_gid)) {
-				msyslog(LOG_ERR, "setgroups(1, %d) failed: %m", sw_gid);
-				exit (-1);
-			}
-		}
-		else if (pw)
-			if (0 != initgroups(pw->pw_name, pw->pw_gid)) {
-				msyslog(LOG_ERR, "initgroups(<%s>, %d) filed: %m", pw->pw_name, pw->pw_gid);
-				exit (-1);
-			}
-		if (user && setuid(sw_uid)) {
-			msyslog(LOG_ERR, "Cannot setuid() to user `%s': %m", user);
-			exit (-1);
-		}
-		if (user && seteuid(sw_uid)) {
-			msyslog(LOG_ERR, "Cannot seteuid() to user `%s': %m", user);
-			exit (-1);
-		}
+		if (0 == set_user_group_ids())
+			exit(-1);
 
 #  if !defined(HAVE_LINUX_CAPABILITIES) && !defined(HAVE_SOLARIS_PRIVS)
 		/*
--- libntp/work_fork.c.orig
+++ libntp/work_fork.c
@@ -33,6 +33,9 @@ static	RETSIGTYPE	worker_sighup(int);
 static	void		send_worker_home_atexit(void);
 static	void		cleanup_after_child(blocking_child *);
 
+# pragma weak set_user_group_ids
+void set_user_group_ids(void);
+
 /* === I/O helpers === */
 /* Since we have signals enabled, there's a good chance that blocking IO
  * via pipe suffers from EINTR -- and this goes for both directions.
@@ -592,6 +595,9 @@ fork_blocking_child(
 	init_logging("ntp_intres", 0, FALSE);
 	setup_logfile(NULL);
 
+	if (NULL != &set_user_group_ids)
+		set_user_group_ids();
+
 	/*
 	 * And now back to the portable code
 	 */
