1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
  
     | 
    
      /* Determine whether string value is affirmation or negative response
   according to current locale's data.
   Copyright (C) 1996, 1998, 2000, 2002-2003, 2006-2023 Free Software
   Foundation, Inc.
   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
#include <config.h>
/* Specification.  */
#include <stdlib.h>
#include <stddef.h>
#if ENABLE_NLS
# include <sys/types.h>
# include <limits.h>
# include <string.h>
# if HAVE_LANGINFO_YESEXPR
#  include <langinfo.h>
# endif
# include <regex.h>
# include "gettext.h"
# define _(msgid) gettext (msgid)
# define N_(msgid) gettext_noop (msgid)
# if HAVE_LANGINFO_YESEXPR
/* Return the localized regular expression pattern corresponding to
   ENGLISH_PATTERN.  NL_INDEX can be used with nl_langinfo.
   The resulting string may only be used until the next nl_langinfo call.  */
static const char *
localized_pattern (const char *english_pattern, nl_item nl_index,
                   bool posixly_correct)
{
  const char *translated_pattern;
  /* We prefer to get the patterns from a PO file.  It would be possible to
     always use nl_langinfo (YESEXPR) instead of _("^[yY]"), and
     nl_langinfo (NOEXPR) instead of _("^[nN]"), if we could assume that the
     system's locale support is good.  But this is not the case e.g. on Cygwin.
     The localizations of gnulib.pot are of better quality in general.
     Also, if we use locale info from non-free systems that don't have a
     'localedef' command, we deprive the users of the freedom to localize
     this pattern for their preferred language.
     But some programs, such as 'cp', 'mv', 'rm', 'find', 'xargs', are
     specified by POSIX to use nl_langinfo (YESEXPR).  We implement this
     behaviour if POSIXLY_CORRECT is set, for the sake of these programs.  */
  /* If the user wants strict POSIX compliance, use nl_langinfo.  */
  if (posixly_correct)
    {
      translated_pattern = nl_langinfo (nl_index);
      /* Check against a broken system return value.  */
      if (translated_pattern != NULL && translated_pattern[0] != '\0')
        return translated_pattern;
   }
  /* Look in the gnulib message catalog.  */
  translated_pattern = _(english_pattern);
  if (translated_pattern == english_pattern)
    {
      /* The gnulib message catalog provides no translation.
         Try the system's message catalog.  */
      translated_pattern = nl_langinfo (nl_index);
      /* Check against a broken system return value.  */
      if (translated_pattern != NULL && translated_pattern[0] != '\0')
        return translated_pattern;
      /* Fall back to English.  */
      translated_pattern = english_pattern;
    }
  return translated_pattern;
}
# else
#  define localized_pattern(english_pattern,nl_index,posixly_correct) \
     _(english_pattern)
# endif
static int
try (const char *response, const char *pattern, char **lastp, regex_t *re)
{
  if (*lastp == NULL || strcmp (pattern, *lastp) != 0)
    {
      char *safe_pattern;
      /* The pattern has changed.  */
      if (*lastp != NULL)
        {
          /* Free the old compiled pattern.  */
          regfree (re);
          free (*lastp);
          *lastp = NULL;
        }
      /* Put the PATTERN into safe memory before calling regcomp.
         (regcomp may call nl_langinfo, overwriting PATTERN's storage.  */
      safe_pattern = strdup (pattern);
      if (safe_pattern == NULL)
        return -1;
      /* Compile the pattern and cache it for future runs.  */
      if (regcomp (re, safe_pattern, REG_EXTENDED) != 0)
        {
          free (safe_pattern);
          return -1;
        }
      *lastp = safe_pattern;
    }
  /* See if the regular expression matches RESPONSE.  */
  return regexec (re, response, 0, NULL, 0) == 0;
}
#endif
int
rpmatch (const char *response)
{
#if ENABLE_NLS
  /* Match against one of the response patterns, compiling the pattern
     first if necessary.  */
  /* We cache the response patterns and compiled regexps here.  */
  static char *last_yesexpr, *last_noexpr;
  static regex_t cached_yesre, cached_nore;
# if HAVE_LANGINFO_YESEXPR
  bool posixly_correct = (getenv ("POSIXLY_CORRECT") != NULL);
# endif
  const char *yesexpr, *noexpr;
  int result;
  /* TRANSLATORS: A regular expression testing for an affirmative answer
     (english: "yes").  Testing the first character may be sufficient.
     Take care to consider upper and lower case.
     To enquire the regular expression that your system uses for this
     purpose, you can use the command
       locale -k LC_MESSAGES | grep '^yesexpr='  */
  yesexpr = localized_pattern (N_("^[yY]"), YESEXPR, posixly_correct);
  result = try (response, yesexpr, &last_yesexpr, &cached_yesre);
  if (result < 0)
    return -1;
  if (result)
    return 1;
  /* TRANSLATORS: A regular expression testing for a negative answer
     (english: "no").  Testing the first character may be sufficient.
     Take care to consider upper and lower case.
     To enquire the regular expression that your system uses for this
     purpose, you can use the command
       locale -k LC_MESSAGES | grep '^noexpr='  */
  noexpr = localized_pattern (N_("^[nN]"), NOEXPR, posixly_correct);
  result = try (response, noexpr, &last_noexpr, &cached_nore);
  if (result < 0)
    return -1;
  if (result)
    return 0;
  return -1;
#else
  /* Test against "^[yY]" and "^[nN]", hardcoded to avoid requiring regex */
  return (*response == 'y' || *response == 'Y' ? 1
          : *response == 'n' || *response == 'N' ? 0 : -1);
#endif
}
 
     |