From: Andrew Bower <andrew@bower.uk>
Date: Tue, 19 Aug 2025 23:17:37 +0100
Bug: https://github.com/openwall/popa3d/issues/1
Forwarded: https://github.com/openwall/popa3d/pull/2
Last-Update: 2025-08-20
Subject: Add foreground server option

New '-F' option is like '-D' but does not fork. This enables improved init
system integration methods and can make up for the lack of a PID file writing
option.
---
 popa3d.8     |  8 ++++++++
 standalone.c | 29 +++++++++++++++++------------
 startup.c    | 12 ++++++++----
 3 files changed, 33 insertions(+), 16 deletions(-)

diff --git a/popa3d.8 b/popa3d.8
index 2fcfca0..d7a0c3d 100644
--- a/popa3d.8
+++ b/popa3d.8
@@ -4,6 +4,7 @@ popa3d \- Post Office Protocol (POP3) server
 .SH SYNOPSIS
 .B popa3d
 .RB [ -D ]
+.RB [ -F ]
 .RB [ -V ]
 .SH DESCRIPTION
 .B popa3d
@@ -44,6 +45,13 @@ In this mode
 also does quite a few checks to significantly reduce the impact of
 connection flood attacks.
 .TP
+.B -F
+Foreground server mode.
+Like
+.B -D
+but staying in the foreground rather than becoming a daemon.
+This supports improved service integration with init systems.
+.TP
 .B -V
 Print version information and exit.
 .SH COMMANDS
diff --git a/standalone.c b/standalone.c
index 216d937..8fb8a2b 100644
--- a/standalone.c
+++ b/standalone.c
@@ -103,11 +103,13 @@ static void check_access(int sock)
 #endif
 
 #if POP_OPTIONS
-int do_standalone(void)
+int do_standalone(int foreground)
+{
 #else
 int main(void)
-#endif
 {
+	int foreground = 0;
+#endif
 	int true = 1;
 	int sock, new;
 	struct sockaddr_in addr;
@@ -137,20 +139,23 @@ int main(void)
 		return log_error("listen");
 
 	chdir("/");
-	setsid();
 
-	switch (fork()) {
-	case -1:
-		return log_error("fork");
+	if (!foreground) {
+		setsid();
 
-	case 0:
-		break;
+		switch (fork()) {
+		case -1:
+			return log_error("fork");
 
-	default:
-		return 0;
-	}
+		case 0:
+			break;
 
-	setsid();
+		default:
+			return 0;
+		}
+
+		setsid();
+	}
 
 #if defined(_SC_CLK_TCK) || !defined(CLK_TCK)
 	min_delay = MIN_DELAY * sysconf(_SC_CLK_TCK);
diff --git a/startup.c b/startup.c
index 25b2b9c..a298015 100644
--- a/startup.c
+++ b/startup.c
@@ -15,7 +15,7 @@ extern char popa3d_version[];
 extern char popa3d_date[];
 
 /* standalone.c */
-extern int do_standalone(void);
+extern int do_standalone(int foreground);
 
 /* pop_root.c */
 extern int do_pop_startup(void);
@@ -30,7 +30,7 @@ static char *progname;
 
 static void usage(void)
 {
-	fprintf(stderr, "Usage: %s [-D] [-V]\n", progname);
+	fprintf(stderr, "Usage: %s [-D] [-F] [-V]\n", progname);
 	exit(1);
 }
 
@@ -44,14 +44,18 @@ int main(int argc, char **argv)
 {
 	int c;
 	int standalone = 0;
+	int foreground = 0;
 
 #ifndef HAVE_PROGNAME
 	if (!(progname = argv[0]))
 		progname = POP_SERVER;
 #endif
 
-	while ((c = getopt(argc, argv, "DV")) != -1) {
+	while ((c = getopt(argc, argv, "DFV")) != -1) {
 		switch (c) {
+		case 'F':
+			foreground++;
+			/* fallthrough */
 		case 'D':
 			standalone++;
 			break;
@@ -68,7 +72,7 @@ int main(int argc, char **argv)
 		usage();
 
 	if (standalone)
-		return do_standalone();
+		return do_standalone(foreground);
 
 	if (do_pop_startup()) return 1;
 	return do_pop_session();
