summaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2006-05-23 18:19:43 +0200
committerWerner Koch <wk@gnupg.org>2006-05-23 18:19:43 +0200
commitfbe4ac37f6d3e7870e26caffb0d21c3c77198297 (patch)
treef21028be87bda6df4f2f1e3ae105feeb5a2eb158 /common
parent2006-05-19 Marcus Brinkmann <marcus@g10code.de> (diff)
downloadgnupg2-fbe4ac37f6d3e7870e26caffb0d21c3c77198297.tar.xz
gnupg2-fbe4ac37f6d3e7870e26caffb0d21c3c77198297.zip
g10/ does build again.
Diffstat (limited to 'common')
-rw-r--r--common/ChangeLog27
-rw-r--r--common/Makefile.am4
-rw-r--r--common/gettime.c28
-rw-r--r--common/iobuf.h2
-rw-r--r--common/miscellaneous.c24
-rw-r--r--common/pka.c252
-rw-r--r--common/pka.h27
-rw-r--r--common/ttyio.c49
-rw-r--r--common/ttyio.h16
-rw-r--r--common/util.h3
-rw-r--r--common/yesno.c142
11 files changed, 518 insertions, 56 deletions
diff --git a/common/ChangeLog b/common/ChangeLog
index f1b11fc57..36a733a7f 100644
--- a/common/ChangeLog
+++ b/common/ChangeLog
@@ -1,3 +1,30 @@
+2006-05-23 Werner Koch <wk@g10code.com>
+
+ * gettime.c (isotimestamp): New.
+
+ * ttyio.c (tty_get_ttyname): Posixly correct usage of ctermid.
+
+ * dns-cert.c: New. Taken from 1.4.3's util/cert.c.
+ * dns-cert.h: New.
+
+2006-05-22 Werner Koch <wk@g10code.com>
+
+ * pka.c: New. Taked from 1.4.3.
+ * pka.h: New.
+ * Makefile.am: Added pka.
+
+2006-05-19 Werner Koch <wk@g10code.com>
+
+ * yesno.c (answer_is_yes_no_default, answer_is_yes_no_quit):
+ Updated from 1.4.3.
+ (answer_is_okay_cancel): new. From 1.4.3.
+
+ * miscellaneous.c (match_multistr): New. Taken from 1.4.3.
+
+ * ttyio.c (tty_enable_completion, tty_disable_completion): New
+ dummy functions.
+ * ttyio.h: Add prototypes and stubs.
+
2006-04-19 Werner Koch <wk@g10code.com>
* iobuf.c (iobuf_get_fd): New. Taken from 1.4.3.
diff --git a/common/Makefile.am b/common/Makefile.am
index 3056be6bc..34819e93f 100644
--- a/common/Makefile.am
+++ b/common/Makefile.am
@@ -49,7 +49,9 @@ libcommon_a_SOURCES = \
w32reg.c \
signal.c \
dynload.h \
- estream.c estream.h
+ estream.c estream.h \
+ dns-cert.c dns-cert.h \
+ pka.c pka.h
libsimple_pwquery_a_SOURCES = \
diff --git a/common/gettime.c b/common/gettime.c
index 93e4ba113..ecdc7df95 100644
--- a/common/gettime.c
+++ b/common/gettime.c
@@ -201,7 +201,7 @@ strtimevalue( u32 value )
}
-/****************
+/*
* Note: this function returns GMT
*/
const char *
@@ -222,6 +222,32 @@ strtimestamp( u32 stamp )
return buffer;
}
+
+/*
+ * Note: this function returns GMT
+ */
+const char *
+isotimestamp (u32 stamp)
+{
+ static char buffer[25+5];
+ struct tm *tp;
+ time_t atime = stamp;
+
+ if (atime < 0)
+ {
+ strcpy (buffer, "????" "-??" "-??" " " "??" ":" "??" ":" "??");
+ }
+ else
+ {
+ tp = gmtime ( &atime );
+ sprintf (buffer,"%04d-%02d-%02d %02d:%02d:%02d",
+ 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday,
+ tp->tm_hour, tp->tm_min, tp->tm_sec);
+ }
+ return buffer;
+}
+
+
/****************
* Note: this function returns local time
*/
diff --git a/common/iobuf.h b/common/iobuf.h
index 431d573a1..3b8f4b572 100644
--- a/common/iobuf.h
+++ b/common/iobuf.h
@@ -145,6 +145,8 @@ void iobuf_set_partial_block_mode (iobuf_t a, size_t len);
int iobuf_translate_file_handle (int fd, int for_write);
+void iobuf_skip_rest (iobuf_t a, unsigned long n, int partial);
+
/* get a byte form the iobuf; must check for eof prior to this function
* this function returns values in the range 0 .. 255 or -1 to indicate EOF
diff --git a/common/miscellaneous.c b/common/miscellaneous.c
index 14d6f020d..e9f8ed27f 100644
--- a/common/miscellaneous.c
+++ b/common/miscellaneous.c
@@ -1,5 +1,5 @@
/* miscellaneous.c - Stuff not fitting elsewhere
- * Copyright (C) 2003 Free Software Foundation, Inc.
+ * Copyright (C) 2003, 2006 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -47,6 +47,7 @@ print_fname_stdin (const char *s)
return s;
}
+/* fixme: Globally replace it by print_sanitized_buffer. */
void
print_string( FILE *fp, const byte *p, size_t n, int delim )
{
@@ -125,4 +126,25 @@ leave:
}
+/* Try match against each substring of multistr, delimited by | */
+int
+match_multistr (const char *multistr,const char *match)
+{
+ do
+ {
+ size_t seglen = strcspn (multistr,"|");
+ if (!seglen)
+ break;
+ /* Using the localized strncasecmp! */
+ if (strncasecmp(multistr,match,seglen)==0)
+ return 1;
+ multistr += seglen;
+ if (*multistr == '|')
+ multistr++;
+ }
+ while (*multistr);
+
+ return 0;
+}
+
diff --git a/common/pka.c b/common/pka.c
new file mode 100644
index 000000000..3d442d16a
--- /dev/null
+++ b/common/pka.c
@@ -0,0 +1,252 @@
+/* pka.c - DNS Public Key Association RR access
+ * Copyright (C) 2005 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef USE_DNS_PKA
+#include <sys/types.h>
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#endif
+#endif /* USE_DNS_PKA */
+
+#include "util.h"
+#include "pka.h"
+
+#ifdef USE_DNS_PKA
+/* Parse the TXT resource record. Format is:
+
+ v=pka1;fpr=a4d94e92b0986ab5ee9dcd755de249965b0358a2;uri=string
+
+ For simplicity white spaces are not allowed. Because we expect to
+ use a new RRTYPE for this in the future we define the TXT really
+ strict for simplicity: No white spaces, case sensitivity of the
+ names, order must be as given above. Only URI is optional.
+
+ This function modifies BUFFER. On success 0 is returned, the 20
+ byte fingerprint stored at FPR and BUFFER contains the URI or an
+ empty string.
+*/
+static int
+parse_txt_record (char *buffer, unsigned char *fpr)
+{
+ char *p, *pend;
+ int i;
+
+ p = buffer;
+ pend = strchr (p, ';');
+ if (!pend)
+ return -1;
+ *pend++ = 0;
+ if (strcmp (p, "v=pka1"))
+ return -1; /* Wrong or missing version. */
+
+ p = pend;
+ pend = strchr (p, ';');
+ if (pend)
+ *pend++ = 0;
+ if (strncmp (p, "fpr=", 4))
+ return -1; /* Missing fingerprint part. */
+ p += 4;
+ for (i=0; i < 20 && hexdigitp (p) && hexdigitp (p+1); i++, p += 2)
+ fpr[i] = xtoi_2 (p);
+ if (i != 20)
+ return -1; /* Fingerprint consists not of exactly 40 hexbytes. */
+
+ p = pend;
+ if (!p || !*p)
+ {
+ *buffer = 0;
+ return 0; /* Success (no URI given). */
+ }
+ if (strncmp (p, "uri=", 4))
+ return -1; /* Unknown part. */
+ p += 4;
+ /* There is an URI, copy it to the start of the buffer. */
+ while (*p)
+ *buffer++ = *p++;
+ *buffer = 0;
+ return 0;
+}
+
+
+/* For the given email ADDRESS lookup the PKA information in the DNS.
+
+ On success the 20 byte SHA-1 fingerprint is stored at FPR and the
+ URI will be returned in an allocated buffer. Note that the URI
+ might be an zero length string as this information is optiobnal.
+ Caller must xfree the returned string.
+
+ On error NULL is returned and the 20 bytes at FPR are not
+ defined. */
+char *
+get_pka_info (const char *address, unsigned char *fpr)
+{
+ unsigned char answer[PACKETSZ];
+ int anslen;
+ int qdcount, ancount, nscount, arcount;
+ int rc;
+ unsigned char *p, *pend;
+ const char *domain;
+ char *name;
+
+
+ domain = strrchr (address, '@');
+ if (!domain || domain == address || !domain[1])
+ return NULL; /* invalid mail address given. */
+
+ name = malloc (strlen (address) + 5 + 1);
+ memcpy (name, address, domain - address);
+ strcpy (stpcpy (name + (domain-address), "._pka."), domain+1);
+
+ anslen = res_query (name, C_IN, T_TXT, answer, PACKETSZ);
+ xfree (name);
+ if (anslen < sizeof(HEADER))
+ return NULL; /* DNS resolver returned a too short answer. */
+ if ( (rc=((HEADER*)answer)->rcode) != NOERROR )
+ return NULL; /* DNS resolver returned an error. */
+
+ /* We assume that PACKETSZ is large enough and don't do dynmically
+ expansion of the buffer. */
+ if (anslen > PACKETSZ)
+ return NULL; /* DNS resolver returned a too long answer */
+
+ qdcount = ntohs (((HEADER*)answer)->qdcount);
+ ancount = ntohs (((HEADER*)answer)->ancount);
+ nscount = ntohs (((HEADER*)answer)->nscount);
+ arcount = ntohs (((HEADER*)answer)->arcount);
+
+ if (!ancount)
+ return NULL; /* Got no answer. */
+
+ p = answer + sizeof (HEADER);
+ pend = answer + anslen; /* Actually points directly behind the buffer. */
+
+ while (qdcount-- && p < pend)
+ {
+ rc = dn_skipname (p, pend);
+ if (rc == -1)
+ return NULL;
+ p += rc + QFIXEDSZ;
+ }
+
+ if (ancount > 1)
+ return NULL; /* more than one possible gpg trustdns record - none used. */
+
+ while (ancount-- && p <= pend)
+ {
+ unsigned int type, class, txtlen, n;
+ char *buffer, *bufp;
+
+ rc = dn_skipname (p, pend);
+ if (rc == -1)
+ return NULL;
+ p += rc;
+ if (p >= pend - 10)
+ return NULL; /* RR too short. */
+
+ type = *p++ << 8;
+ type |= *p++;
+ class = *p++ << 8;
+ class |= *p++;
+ p += 4;
+ txtlen = *p++ << 8;
+ txtlen |= *p++;
+ if (type != T_TXT || class != C_IN)
+ return NULL; /* Answer does not match the query. */
+
+ buffer = bufp = xmalloc (txtlen + 1);
+ while (txtlen && p < pend)
+ {
+ for (n = *p++, txtlen--; txtlen && n && p < pend; txtlen--, n--)
+ *bufp++ = *p++;
+ }
+ *bufp = 0;
+ if (parse_txt_record (buffer, fpr))
+ {
+ xfree (buffer);
+ return NULL; /* Not a valid gpg trustdns RR. */
+ }
+ return buffer;
+ }
+
+ return NULL;
+}
+#else /* !USE_DNS_PKA */
+
+/* Dummy version of the function if we can't use the resolver
+ functions. */
+char *
+get_pka_info (const char *address, unsigned char *fpr)
+{
+ return NULL;
+}
+#endif /* !USE_DNS_PKA */
+
+
+#ifdef TEST
+int
+main(int argc,char *argv[])
+{
+ unsigned char fpr[20];
+ char *uri;
+ int i;
+
+ if (argc < 2)
+ {
+ fprintf (stderr, "usage: pka mail-addresses\n");
+ return 1;
+ }
+ argc--;
+ argv++;
+
+ for (; argc; argc--, argv++)
+ {
+ uri = get_pka_info ( *argv, fpr );
+ printf ("%s", *argv);
+ if (uri)
+ {
+ putchar (' ');
+ for (i=0; i < 20; i++)
+ printf ("%02X", fpr[i]);
+ if (*uri)
+ printf (" %s", uri);
+ xfree (uri);
+ }
+ putchar ('\n');
+ }
+ return 0;
+}
+#endif /* TEST */
+
+/*
+Local Variables:
+compile-command: "cc -DUSE_DNS_PKA -DTEST -I.. -I../include -Wall -g -o pka pka.c -lresolv libutil.a"
+End:
+*/
diff --git a/common/pka.h b/common/pka.h
new file mode 100644
index 000000000..d0b977d0f
--- /dev/null
+++ b/common/pka.h
@@ -0,0 +1,27 @@
+/* pka.h - DNS Public Key Association RR access definitions
+ * Copyright (C) 2006 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+#ifndef GNUPG_COMMON_PKA_H
+#define GNUPG_COMMON_PKA_H
+
+char *get_pka_info (const char *address, unsigned char *fpr);
+
+
+#endif /*GNUPG_COMMON_PKA_H*/
diff --git a/common/ttyio.c b/common/ttyio.c
index 5749c59fe..c9f41c626 100644
--- a/common/ttyio.c
+++ b/common/ttyio.c
@@ -1,5 +1,6 @@
/* ttyio.c - tty i/O functions
- * Copyright (C) 1998,1999,2000,2001,2002,2003 Free Software Foundation, Inc.
+ * Copyright (C) 1998,1999,2000,2001,2002,2003,
+ * 2004, 2006 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -45,6 +46,12 @@
#endif
#include <errno.h>
#include <ctype.h>
+#ifdef HAVE_LIBREADLINE
+#include <readline/readline.h>
+#include <readline/history.h>
+#endif
+
+
#include "util.h"
#include "memory.h"
#include "ttyio.h"
@@ -93,13 +100,21 @@ tty_get_ttyname (void)
if (!got_name)
{
const char *s;
+ /* Note that despite our checks for these macros the function is
+ not necessarily thread save. We mainly do this for
+ portability reasons, in case L_ctermid is not defined. */
+# if defined(_POSIX_THREAD_SAFE_FUNCTIONS) || defined(_POSIX_TRHEADS)
+ char buffer[L_ctermid];
+ s = ctermid (buffer);
+# else
s = ctermid (NULL);
+# endif
if (s)
name = strdup (s);
got_name = 1;
}
-#endif
- /* Assume the staandrd tty on memory error or when tehre is no
+#endif /*HAVE_CTERMID*/
+ /* Assume the standard tty on memory error or when tehre is no
certmid. */
return name? name : "/dev/tty";
}
@@ -165,6 +180,34 @@ init_ttyfp(void)
}
+#ifdef HAVE_LIBREADLINE
+void
+tty_enable_completion(rl_completion_func_t *completer)
+{
+/* if( no_terminal ) */
+/* return; */
+
+/* if( !initialized ) */
+/* init_ttyfp(); */
+
+/* rl_attempted_completion_function=completer; */
+/* rl_inhibit_completion=0; */
+}
+
+void
+tty_disable_completion(void)
+{
+/* if( no_terminal ) */
+/* return; */
+
+/* if( !initialized ) */
+/* init_ttyfp(); */
+
+/* rl_inhibit_completion=1; */
+}
+#endif /*HAVE_LIBREADLINE*/
+
+
int
tty_batchmode( int onoff )
{
diff --git a/common/ttyio.h b/common/ttyio.h
index 6fa7400a9..6148d644a 100644
--- a/common/ttyio.h
+++ b/common/ttyio.h
@@ -20,6 +20,11 @@
#ifndef GNUPG_COMMON_TTYIO_H
#define GNUPG_COMMON_TTYIO_H
+#ifdef HAVE_LIBREADLINE
+#include <stdio.h>
+#include <readline/readline.h>
+#endif
+
const char *tty_get_ttyname (void);
int tty_batchmode (int onoff);
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
@@ -40,5 +45,16 @@ void tty_kill_prompt (void);
int tty_get_answer_is_yes (const char *prompt);
int tty_no_terminal (int onoff);
+#ifdef HAVE_LIBREADLINE
+void tty_enable_completion(rl_completion_func_t *completer);
+void tty_disable_completion(void);
+#else
+/* Use a macro to stub out these functions since a macro has no need
+ to typedef a "rl_completion_func_t" which would be undefined
+ without readline. */
+#define tty_enable_completion(x)
+#define tty_disable_completion()
+#endif
+
#endif /*GNUPG_COMMON_TTYIO_H*/
diff --git a/common/util.h b/common/util.h
index 68f5222b5..295d785c5 100644
--- a/common/util.h
+++ b/common/util.h
@@ -84,6 +84,7 @@ u32 scan_isodatestr (const char *string);
u32 add_days_to_timestamp (u32 stamp, u16 days);
const char *strtimevalue (u32 stamp);
const char *strtimestamp (u32 stamp); /* GMT */
+const char *isotimestamp (u32 stamp); /* GMT */
const char *asctimestamp (u32 stamp); /* localized */
@@ -108,6 +109,7 @@ void gnupg_unblock_all_signals (void);
int answer_is_yes (const char *s);
int answer_is_yes_no_default (const char *s, int def_answer);
int answer_is_yes_no_quit (const char *s);
+int answer_is_okay_cancel (const char *s, int def_answer);
/*-- xreadline.c --*/
ssize_t read_line (FILE *fp,
@@ -161,6 +163,7 @@ char *make_printable_string (const void *p, size_t n, int delim);
int is_file_compressed (const char *s, int *ret_rc);
+int match_multistr (const char *multistr,const char *match);
/*-- Simple replacement functions. */
diff --git a/common/yesno.c b/common/yesno.c
index 2a96b4e5d..737071691 100644
--- a/common/yesno.c
+++ b/common/yesno.c
@@ -28,31 +28,33 @@
int
answer_is_yes_no_default( const char *s, int def_answer )
{
- const char *long_yes = _("yes");
- const char *short_yes = _("yY");
- const char *long_no = _("no");
- const char *short_no = _("nN");
+ /* TRANSLATORS: See doc/TRANSLATE about this string. */
+ const char *long_yes = _("yes");
+ const char *short_yes = _("yY");
+ /* TRANSLATORS: See doc/TRANSLATE about this string. */
+ const char *long_no = _("no");
+ const char *short_no = _("nN");
- /* Note: we have to use the local dependent strcasecmp here */
- if( !strcasecmp(s, long_yes ) )
- return 1;
- if( *s && strchr( short_yes, *s ) && !s[1] )
- return 1;
- /* test for no strings to catch ambiguities for the next test */
- if( !strcasecmp(s, long_no ) )
- return 0;
- if( *s && strchr( short_no, *s ) && !s[1] )
- return 0;
- /* test for the english version (for those who are used to type yes) */
- if( !ascii_strcasecmp(s, "yes" ) )
- return 1;
- if( *s && strchr( "yY", *s ) && !s[1] )
- return 1;
- return def_answer;
+ /* Note: we have to use the local dependent compare here. */
+ if ( match_multistr(long_yes,s) )
+ return 1;
+ if ( *s && strchr( short_yes, *s ) && !s[1] )
+ return 1;
+ /* Test for "no" strings to catch ambiguities for the next test. */
+ if ( match_multistr(long_no,s) )
+ return 0;
+ if ( *s && strchr( short_no, *s ) && !s[1] )
+ return 0;
+ /* Test for the english version (for those who are used to type yes). */
+ if ( !ascii_strcasecmp(s, "yes" ) )
+ return 1;
+ if ( *s && strchr( "yY", *s ) && !s[1] )
+ return 1;
+ return def_answer;
}
int
-answer_is_yes( const char *s )
+answer_is_yes ( const char *s )
{
return answer_is_yes_no_default(s,0);
}
@@ -61,36 +63,76 @@ answer_is_yes( const char *s )
* Return 1 for yes, -1 for quit, or 0 for no
*/
int
-answer_is_yes_no_quit( const char *s )
+answer_is_yes_no_quit ( const char *s )
{
- const char *long_yes = _("yes");
- const char *long_no = _("no");
- const char *long_quit = _("quit");
- const char *short_yes = _("yY");
- const char *short_no = _("nN");
- const char *short_quit = _("qQ");
+ /* TRANSLATORS: See doc/TRANSLATE about this string. */
+ const char *long_yes = _("yes");
+ /* TRANSLATORS: See doc/TRANSLATE about this string. */
+ const char *long_no = _("no");
+ /* TRANSLATORS: See doc/TRANSLATE about this string. */
+ const char *long_quit = _("quit");
+ const char *short_yes = _("yY");
+ const char *short_no = _("nN");
+ const char *short_quit = _("qQ");
- /* Note: We have to use the locale dependent strcasecmp */
- if( !strcasecmp(s, long_no ) )
- return 0;
- if( !strcasecmp(s, long_yes ) )
- return 1;
- if( !strcasecmp(s, long_quit ) )
- return -1;
- if( *s && strchr( short_no, *s ) && !s[1] )
- return 0;
- if( *s && strchr( short_yes, *s ) && !s[1] )
- return 1;
- if( *s && strchr( short_quit, *s ) && !s[1] )
- return -1;
- /* but not here */
- if( !ascii_strcasecmp(s, "yes" ) )
- return 1;
- if( !ascii_strcasecmp(s, "quit" ) )
- return -1;
- if( *s && strchr( "yY", *s ) && !s[1] )
- return 1;
- if( *s && strchr( "qQ", *s ) && !s[1] )
- return -1;
+ /* Note: we have to use a local dependent compare here. */
+ if ( match_multistr(long_no,s) )
return 0;
+ if ( match_multistr(long_yes,s) )
+ return 1;
+ if ( match_multistr(long_quit,s) )
+ return -1;
+ if ( *s && strchr( short_no, *s ) && !s[1] )
+ return 0;
+ if ( *s && strchr( short_yes, *s ) && !s[1] )
+ return 1;
+ if ( *s && strchr( short_quit, *s ) && !s[1] )
+ return -1;
+ /* but not here. */
+ if ( !ascii_strcasecmp(s, "yes" ) )
+ return 1;
+ if ( !ascii_strcasecmp(s, "quit" ) )
+ return -1;
+ if ( *s && strchr( "yY", *s ) && !s[1] )
+ return 1;
+ if ( *s && strchr( "qQ", *s ) && !s[1] )
+ return -1;
+ return 0;
}
+
+/*
+ Return 1 for okay, 0 for for cancel or DEF_ANSWER for default.
+ */
+int
+answer_is_okay_cancel (const char *s, int def_answer)
+{
+ /* TRANSLATORS: See doc/TRANSLATE about this string. */
+ const char *long_okay = _("okay|okay");
+ /* TRANSLATORS: See doc/TRANSLATE about this string. */
+ const char *long_cancel = _("cancel|cancel");
+ const char *short_okay = _("oO");
+ const char *short_cancel = _("cC");
+
+ /* Note: We have to use the locale dependent compare. */
+ if ( match_multistr(long_okay,s) )
+ return 1;
+ if ( match_multistr(long_cancel,s) )
+ return 0;
+ if ( *s && strchr( short_okay, *s ) && !s[1] )
+ return 1;
+ if ( *s && strchr( short_cancel, *s ) && !s[1] )
+ return 0;
+ /* Always test for the English values (not locale here). */
+ if ( !ascii_strcasecmp(s, "okay" ) )
+ return 1;
+ if ( !ascii_strcasecmp(s, "ok" ) )
+ return 1;
+ if ( !ascii_strcasecmp(s, "cancel" ) )
+ return 0;
+ if ( *s && strchr( "oO", *s ) && !s[1] )
+ return 1;
+ if ( *s && strchr( "cC", *s ) && !s[1] )
+ return 0;
+ return def_answer;
+}
+