git: 550dacea138e - main - Revert "libc/resolv: Refactor the option parser"

From: Dag-Erling Smørgrav <des_at_FreeBSD.org>
Date: Mon, 29 Jun 2026 15:54:29 UTC
The branch main has been updated by des:

URL: https://cgit.FreeBSD.org/src/commit/?id=550dacea138e5df66780a152ab1ba91c466d7395

commit 550dacea138e5df66780a152ab1ba91c466d7395
Author:     Dag-Erling Smørgrav <des@FreeBSD.org>
AuthorDate: 2026-06-29 15:54:00 +0000
Commit:     Dag-Erling Smørgrav <des@FreeBSD.org>
CommitDate: 2026-06-29 15:54:00 +0000

    Revert "libc/resolv: Refactor the option parser"
    
    This reverts commit 40e10af6c6dc46d9c0835db3dc95368ce7d69b55.
---
 lib/libc/resolv/res_init.c | 165 +++++++++++++++++++++------------------------
 1 file changed, 77 insertions(+), 88 deletions(-)

diff --git a/lib/libc/resolv/res_init.c b/lib/libc/resolv/res_init.c
index 20f6824857b5..e9e982fe27bb 100644
--- a/lib/libc/resolv/res_init.c
+++ b/lib/libc/resolv/res_init.c
@@ -3,7 +3,6 @@
  *
  * Copyright (c) 1985, 1989, 1993
  *    The Regents of the University of California.  All rights reserved.
- * Copyright (c) 2026 Dag-Erling Smørgrav
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -81,7 +80,6 @@
 #include <arpa/nameser.h>
 
 #include <ctype.h>
-#include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -105,11 +103,9 @@ static const char sort_mask[] = "/&";
 static u_int32_t net_mask(struct in_addr);
 #endif
 
-#define res_space(ch)							\
-	isspace((unsigned char)(ch))
-#define res_match(str, end, word)					\
-	(strncmp((str), (word), (end) - (str)) == 0 &&			\
-	    (word)[(end) - (str)] == '\0')
+#if !defined(isascii)	/*%< XXX - could be a function */
+# define isascii(c) (!(c & 0200))
+#endif
 
 /*
  * Resolver state default settings.
@@ -524,136 +520,129 @@ __res_vinit(res_state statp, int preinit) {
 static void
 res_setoptions(res_state statp, const char *options, const char *source)
 {
-	const char *cp = options, *sp, *ep;
-	char *numend;
-	long num;
+	const char *cp = options;
+	int i;
 	struct __res_state_ext *ext = statp->_u._ext.ext;
 
 #ifdef DEBUG
-	if (statp->options & RES_DEBUG) {
+	if (statp->options & RES_DEBUG)
 		printf(";; res_setoptions(\"%s\", \"%s\")...\n",
 		       options, source);
-	}
 #endif
-	for (;;) {
+	while (*cp) {
 		/* skip leading and inner runs of spaces */
-		while (res_space(*cp))
+		while (*cp == ' ' || *cp == '\t')
 			cp++;
-		/* find the separator if there is one */
-		sp = cp;
-		while (*sp != '\0' && !res_space(*sp) && *sp != ':')
-			sp++;
-		/* find the end of the option */
-		ep = sp;
-		while (*ep != '\0' && !res_space(*ep))
-			ep++;
-		/* end of option line */
-		if (ep == cp)
-			break;
 		/* search for and process individual options */
-		if (res_match(cp, sp, "ndots") && sp < ep) {
-			num = strtol(sp + 1, &numend, 10);
-			if (numend == ep && num <= RES_MAXNDOTS)
-				statp->ndots = num;
+		if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) {
+			i = atoi(cp + sizeof("ndots:") - 1);
+			if (i <= RES_MAXNDOTS)
+				statp->ndots = i;
 			else
 				statp->ndots = RES_MAXNDOTS;
 #ifdef DEBUG
 			if (statp->options & RES_DEBUG)
 				printf(";;\tndots=%d\n", statp->ndots);
 #endif
-		} else if (res_match(cp, sp, "timeout") && sp < ep) {
-			num = strtol(sp + 1, &numend, 10);
-			if (numend == ep && num > 0 && num <= RES_MAXRETRANS)
-				statp->retrans = num;
+		} else if (!strncmp(cp, "timeout:", sizeof("timeout:") - 1)) {
+			i = atoi(cp + sizeof("timeout:") - 1);
+			if (i <= RES_MAXRETRANS)
+				statp->retrans = i;
 			else
 				statp->retrans = RES_MAXRETRANS;
 #ifdef DEBUG
 			if (statp->options & RES_DEBUG)
 				printf(";;\ttimeout=%d\n", statp->retrans);
 #endif
-		} else if (res_match(cp, sp, "attempts") && sp < ep) {
-			num = strtol(sp + 1, &numend, 10);
-			if (numend == ep && num > 0 && num <= RES_MAXRETRY)
-				statp->retry = num;
+		} else if (!strncmp(cp, "attempts:", sizeof("attempts:") - 1)){
+			i = atoi(cp + sizeof("attempts:") - 1);
+			if (i <= RES_MAXRETRY)
+				statp->retry = i;
 			else
 				statp->retry = RES_MAXRETRY;
 #ifdef DEBUG
 			if (statp->options & RES_DEBUG)
 				printf(";;\tattempts=%d\n", statp->retry);
 #endif
-		} else if (res_match(cp, ep, "debug")) {
+		} else if (!strncmp(cp, "debug", sizeof("debug") - 1)) {
 #ifdef DEBUG
 			if (!(statp->options & RES_DEBUG)) {
 				printf(";; res_setoptions(\"%s\", \"%s\")..\n",
 				       options, source);
+				statp->options |= RES_DEBUG;
 			}
-#endif
-			statp->options |= RES_DEBUG;
-#ifdef DEBUG
 			printf(";;\tdebug\n");
 #endif
-		} else if (res_match(cp, ep, "no-tld-query") ||
-		    res_match(cp, ep, "no_tld_query")) {
+		} else if (!strncmp(cp, "no_tld_query",
+				    sizeof("no_tld_query") - 1) ||
+			   !strncmp(cp, "no-tld-query",
+				    sizeof("no-tld-query") - 1)) {
 			statp->options |= RES_NOTLDQUERY;
-		} else if (res_match(cp, ep, "inet6")) {
+		} else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) {
 			statp->options |= RES_USE_INET6;
-		} else if (res_match(cp, ep, "insecure1")) {
-			statp->options |= RES_INSECURE1;
-		} else if (res_match(cp, ep, "insecure2")) {
-			statp->options |= RES_INSECURE2;
-		} else if (res_match(cp, ep, "blast")) {
-			statp->options |= RES_BLAST;
-		} else if (res_match(cp, ep, "rotate")) {
+		} else if (!strncmp(cp, "insecure1", sizeof("insecure1") - 1)) {
+		       statp->options |= RES_INSECURE1;
+		} else if (!strncmp(cp, "insecure2", sizeof("insecure2") - 1)) {
+		       statp->options |= RES_INSECURE2;
+		} else if (!strncmp(cp, "rotate", sizeof("rotate") - 1)) {
 			statp->options |= RES_ROTATE;
-		} else if (res_match(cp, ep, "usevc")) {
+		} else if (!strncmp(cp, "usevc", sizeof("usevc") - 1)) {
 			statp->options |= RES_USEVC;
-		} else if (res_match(cp, ep, "no-check-names")) {
+		} else if (!strncmp(cp, "no-check-names",
+				    sizeof("no-check-names") - 1)) {
 			statp->options |= RES_NOCHECKNAME;
-		} else if (res_match(cp, sp, "reload-period") && sp < ep) {
-			num = strtol(sp + 1, &numend, 10);
-			if (numend == ep && num > 0 && num <= USHRT_MAX &&
-			    ext != NULL) {
-				ext->reload_period = (u_short)num;
+		} else if (!strncmp(cp, "reload-period:",
+				    sizeof("reload-period:") - 1)) {
+			if (ext != NULL) {
+				ext->reload_period = (u_short)
+				    atoi(cp + sizeof("reload-period:") - 1);
 			}
+		}
 #ifdef RES_USE_EDNS0
-		} else if (res_match(cp, ep, "edns0")) {
+		else if (!strncmp(cp, "edns0", sizeof("edns0") - 1)) {
 			statp->options |= RES_USE_EDNS0;
+		}
 #endif
 #ifndef _LIBC
-		} else if (res_match(cp, ep, "dname")) {
+		else if (!strncmp(cp, "dname", sizeof("dname") - 1)) {
 			statp->options |= RES_USE_DNAME;
-		} else if (res_match(cp, sp, "nibble") && sp < ep) {
-			sp++;
-			if (ext != NULL && ep - sp < sizeof(ext->nsuffix)) {
-				strncpy(ext->nsuffix, sp, ep - sp);
-				ext->nsuffix[ep - sp] = '\0';
-			}
-		} else if (res_match(cp, sp, "nibble2") && sp < ep) {
-			sp++;
-			if (ext != NULL && ep - sp < sizeof(ext->nsuffix2)) {
-				strncpy(ext->nsuffix2, sp, ep - sp);
-				ext->nsuffix2[ep - sp] = '\0';
-			}
-		} else if (res_match(cp, sp, "v6revmode") && sp < ep) {
+		}
+		else if (!strncmp(cp, "nibble:", sizeof("nibble:") - 1)) {
+			if (ext == NULL)
+				goto skip;
+			cp += sizeof("nibble:") - 1;
+			i = MIN(strcspn(cp, " \t"), sizeof(ext->nsuffix) - 1);
+			strncpy(ext->nsuffix, cp, i);
+			ext->nsuffix[i] = '\0';
+		}
+		else if (!strncmp(cp, "nibble2:", sizeof("nibble2:") - 1)) {
+			if (ext == NULL)
+				goto skip;
+			cp += sizeof("nibble2:") - 1;
+			i = MIN(strcspn(cp, " \t"), sizeof(ext->nsuffix2) - 1);
+			strncpy(ext->nsuffix2, cp, i);
+			ext->nsuffix2[i] = '\0';
+		}
+		else if (!strncmp(cp, "v6revmode:", sizeof("v6revmode:") - 1)) {
+			cp += sizeof("v6revmode:") - 1;
 			/* "nibble" and "bitstring" used to be valid */
-			if (res_match(sp + 1, ep, "single"))
+			if (!strncmp(cp, "single", sizeof("single") - 1)) {
 				statp->options |= RES_NO_NIBBLE2;
-			else if (res_match(sp + 1, ep, "both"))
-				statp->options &= ~RES_NO_NIBBLE2;
-#ifdef DEBUG
-			else
-				printf(";;\t%.*s: unrecognized value: %.*s\n",
-				    (int)(sp - cp), cp,
-				    (int)(ep - sp - 1), sp + 1);
-#endif
-#endif /* !_LIBC */
-		} else {
-#ifdef DEBUG
-			printf(";;\tunrecognized option: %.*s\n",
-			    (int)(ep - cp), cp);
+			} else if (!strncmp(cp, "both", sizeof("both") - 1)) {
+				statp->options &=
+					 ~RES_NO_NIBBLE2;
+			}
+		}
 #endif
+		else {
+			/* XXX - print a warning here? */
 		}
-		cp = ep;
+#ifndef _LIBC
+   skip:
+#endif
+		/* skip to next run of spaces */
+		while (*cp && *cp != ' ' && *cp != '\t')
+			cp++;
 	}
 }