libmisc/yesno.c: Use getline(3) and rpmatch(3)
getline(3) is much more readable than manually looping. It has some overhead due to the allocation of a buffer, but that shouldn't be a problem here. If that was a problem, we could reuse the buffer (thus making the function non-reentrant), but I don't think that's worth the extra complexity. Using rpmatch(3) instead of a simple y/n test provides i18n to the response checking. We have a fall-back minimalistic implementation for systems that lack this function (e.g., musl libc). While we're at it, apply some other minor improvements to this file: - Remove comment saying which files use this function. That's likely to get outdated. And anyway, it's just a grep(1) away, so it doesn't really add any value. - Remove unnecessary casts to (void) that were used to verbosely ignore errors from stdio calls. They add clutter without really adding much value to the code (or I don't see it). - Remove comments from the function body. They make the function less readable. Instead, centralize the description of the function into a man-page-like comment before the function definition. This keeps the function body short and sweet. - Add '#include <stdbool.h>', which was missing. - Minor whitespace style changes (it doesn't hurt the diff at this point, since most of the affected lines were already touched by other changes, so I applied my preferred style :). Acked-by: Samanta Navarro <ferivoz@riseup.net> Cc: Serge Hallyn <serge@hallyn.com> Signed-off-by: Alejandro Colomar <alx@kernel.org>
This commit is contained in:
		
				
					committed by
					
						 Serge Hallyn
						Serge Hallyn
					
				
			
			
				
	
			
			
			
						parent
						
							7b686d8bd6
						
					
				
				
					commit
					e28deeb8e9
				
			| @@ -50,6 +50,7 @@ AC_CHECK_FUNCS(arc4random_buf futimes \ | ||||
| 	initgroups lckpwdf lutimes mempcpy \ | ||||
| 	setgroups updwtmp updwtmpx innetgr \ | ||||
| 	getspnam_r \ | ||||
| 	rpmatch \ | ||||
| 	memset_explicit explicit_bzero stpecpy stpeprintf) | ||||
| AC_SYS_LARGEFILE | ||||
|  | ||||
|   | ||||
| @@ -1,59 +1,84 @@ | ||||
| /* | ||||
|  * SPDX-FileCopyrightText: 1992 - 1994, Julianne Frances Haugh | ||||
|  * SPDX-FileCopyrightText: 2007 - 2008, Nicolas François | ||||
|  * SPDX-FileCopyrightText: 2023, Alejandro Colomar <alx@kernel.org> | ||||
|  * | ||||
|  * SPDX-License-Identifier: BSD-3-Clause | ||||
|  */ | ||||
|  | ||||
| /* | ||||
|  * Common code for yes/no prompting | ||||
|  * | ||||
|  * Used by pwck.c and grpck.c | ||||
|  */ | ||||
|  | ||||
| #include <config.h> | ||||
|  | ||||
| #ident "$Id$" | ||||
|  | ||||
| #include <stdbool.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include "prototypes.h" | ||||
|  | ||||
| /* | ||||
|  * yes_or_no - get answer to question from the user | ||||
|  * | ||||
|  *	It returns false if no. | ||||
|  * | ||||
|  *	If the read_only flag is set, it will print No, and will return | ||||
|  *	false. | ||||
|  */ | ||||
| bool yes_or_no (bool read_only) | ||||
| { | ||||
| 	int c; | ||||
| 	bool result; | ||||
|  | ||||
| 	/* | ||||
| 	 * In read-only mode all questions are answered "no". | ||||
| 	 */ | ||||
| /* | ||||
|  * Synopsis | ||||
|  *	bool yes_or_no(bool read_only); | ||||
|  * | ||||
|  * Arguments | ||||
|  *	read_only | ||||
|  *		In read-only mode, all questions are answered "no".  It | ||||
|  *		will print "No" to stdout. | ||||
|  * | ||||
|  * Description | ||||
|  *	After a yes/no question, this function gets the answer from the | ||||
|  *	user. | ||||
|  * | ||||
|  *	Calls to this function will normally be preceeded by a prompt on | ||||
|  *	stdout, so we should fflush(3). | ||||
|  * | ||||
|  * Return value | ||||
|  *	false	"no" | ||||
|  *	true	"yes" | ||||
|  * | ||||
|  * See also | ||||
|  *	rpmatch(3) | ||||
|  */ | ||||
|  | ||||
|  | ||||
| #if !defined(HAVE_RPMATCH) | ||||
| static int rpmatch(const char *response); | ||||
| #endif | ||||
|  | ||||
|  | ||||
| bool | ||||
| yes_or_no(bool read_only) | ||||
| { | ||||
| 	bool  ret; | ||||
| 	char  *buf; | ||||
|  | ||||
| 	if (read_only) { | ||||
| 		(void) puts (_("No")); | ||||
| 		puts(_("No")); | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	/* | ||||
| 	 * Typically, there's a prompt on stdout, sometimes unflushed. | ||||
| 	 */ | ||||
| 	(void) fflush (stdout); | ||||
| 	fflush(stdout); | ||||
|  | ||||
| 	/* | ||||
| 	 * Get a line and see what the first character is. | ||||
| 	 */ | ||||
| 	c = fgetc(stdin); | ||||
| 	/* TODO: use gettext */ | ||||
| 	result = (c == 'y' || c == 'Y'); | ||||
| 	ret = false; | ||||
| 	if (getline(&buf, NULL, stdin) != NULL) | ||||
| 		ret = rpmatch(buf) == 1; | ||||
|  | ||||
| 	while (c != '\n' && c != EOF) | ||||
| 		c = fgetc(stdin); | ||||
|  | ||||
| 	return result; | ||||
| 	free(buf); | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
|  | ||||
| #if !defined(HAVE_RPMATCH) | ||||
| static int | ||||
| rpmatch(const char *response) | ||||
| { | ||||
| 	if (response[0] == 'y' || response[0] == 'Y') | ||||
| 		return 1; | ||||
|  | ||||
| 	if (response[0] == 'n' || response[0] == 'n') | ||||
| 		return 0; | ||||
|  | ||||
| 	return -1; | ||||
| } | ||||
| #endif | ||||
|   | ||||
		Reference in New Issue
	
	Block a user