diff --git a/configure.ac b/configure.ac index f4c29ca4..d75b99ff 100644 --- a/configure.ac +++ b/configure.ac @@ -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 diff --git a/libmisc/yesno.c b/libmisc/yesno.c index d8847e40..2ef4d9fa 100644 --- a/libmisc/yesno.c +++ b/libmisc/yesno.c @@ -1,59 +1,84 @@ /* * SPDX-FileCopyrightText: 1992 - 1994, Julianne Frances Haugh * SPDX-FileCopyrightText: 2007 - 2008, Nicolas François + * SPDX-FileCopyrightText: 2023, Alejandro Colomar * * SPDX-License-Identifier: BSD-3-Clause */ -/* - * Common code for yes/no prompting - * - * Used by pwck.c and grpck.c - */ #include #ident "$Id$" +#include #include +#include #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