From e6be21d4b1070e94dcab0d92a590186676823b71 Mon Sep 17 00:00:00 2001
From: Sehrope Sarkuni <sehrope@jackdb.com>
Date: Sat, 29 Aug 2026 13:55:44 +0000
Subject: [PATCH 3/4] Do not take a moved non-option as an option argument in
 port getopt_long()

Non-options are moved to the end of argv as they are found, so one
that preceded an option was already behind it when the option looked
for its argument. "foo -b" parsed as -b with argument foo instead of
reporting the missing argument.
---
 src/port/getopt_long.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/src/port/getopt_long.c b/src/port/getopt_long.c
index 7489a0206ee..269762280d8 100644
--- a/src/port/getopt_long.c
+++ b/src/port/getopt_long.c
@@ -65,6 +65,7 @@ getopt_long(int argc, char *const argv[],
 	const char *oli;			/* option letter list index */
 	static int	nonopt_start = -1;
 	static bool force_nonopt = false;
+	int			argend;
 
 	if (!*place)
 	{							/* update scanning pointer */
@@ -135,11 +136,18 @@ retry:
 
 					if (has_arg != no_argument)
 					{
+						/*
+						 * Non-options already moved to the back of argv
+						 * preceded this option, so they cannot be its
+						 * argument.
+						 */
+						argend = (nonopt_start == -1) ? argc : nonopt_start;
+
 						if (place[namelen] == '=')
 							optarg = place + namelen + 1;
 						else if (has_arg == optional_argument)
 							optarg = NULL;
-						else if (optind < argc - 1)
+						else if (optind < argend - 1)
 						{
 							optind++;
 							optarg = argv[optind];
@@ -213,9 +221,11 @@ retry:
 	}
 	else
 	{							/* need an argument */
+		argend = (nonopt_start == -1) ? argc : nonopt_start;
+
 		if (*place)				/* no white space */
 			optarg = place;
-		else if (argc <= ++optind)
+		else if (argend <= ++optind)
 		{						/* no arg */
 			place = EMSG;
 			if (*optstring == ':')
-- 
2.17.1

