summaryrefslogtreecommitdiffstats
path: root/debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry
diff options
context:
space:
mode:
Diffstat (limited to 'debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry')
-rw-r--r--debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/Makefile.am44
-rw-r--r--debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/Makefile.in696
-rw-r--r--debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/argparse.c1608
-rw-r--r--debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/argparse.h204
-rw-r--r--debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/password-cache.c172
-rw-r--r--debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/password-cache.h30
-rw-r--r--debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/pinentry-curses.c1410
-rw-r--r--debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/pinentry-curses.h35
-rw-r--r--debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/pinentry-emacs.c721
-rw-r--r--debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/pinentry-emacs.h47
-rw-r--r--debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/pinentry.c2067
-rw-r--r--debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/pinentry.h364
12 files changed, 7398 insertions, 0 deletions
diff --git a/debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/Makefile.am b/debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/Makefile.am
new file mode 100644
index 00000000..0866ccec
--- /dev/null
+++ b/debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/Makefile.am
@@ -0,0 +1,44 @@
+# Pinentry support library Makefile
+# Copyright (C) 2002, 2015 g10 Code GmbH
+#
+# This file is part of PINENTRY.
+#
+# PINENTRY 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.
+#
+# PINENTRY 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/>.
+# SPDX-License-Identifier: GPL-2.0+
+
+## Process this file with automake to produce Makefile.in
+
+EXTRA_DIST =
+
+if BUILD_LIBPINENTRY_CURSES
+pinentry_curses = libpinentry-curses.a
+else
+pinentry_curses =
+endif
+
+if BUILD_LIBPINENTRY_EMACS
+pinentry_emacs_sources = pinentry-emacs.h pinentry-emacs.c
+else
+pinentry_emacs_sources =
+endif
+
+noinst_LIBRARIES = libpinentry.a $(pinentry_curses)
+
+LDADD = $(COMMON_LIBS)
+AM_CPPFLAGS = $(COMMON_CFLAGS) -I$(top_srcdir)/secmem
+
+libpinentry_a_SOURCES = pinentry.h pinentry.c argparse.c argparse.h \
+ password-cache.h password-cache.c $(pinentry_emacs_sources)
+libpinentry_curses_a_SOURCES = pinentry-curses.h pinentry-curses.c
+libpinentry_curses_a_CFLAGS = @NCURSES_CFLAGS@
diff --git a/debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/Makefile.in b/debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/Makefile.in
new file mode 100644
index 00000000..5d4f9154
--- /dev/null
+++ b/debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/Makefile.in
@@ -0,0 +1,696 @@
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Pinentry support library Makefile
+# Copyright (C) 2002, 2015 g10 Code GmbH
+#
+# This file is part of PINENTRY.
+#
+# PINENTRY 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.
+#
+# PINENTRY 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/>.
+# SPDX-License-Identifier: GPL-2.0+
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = pinentry
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/curses.m4 \
+ $(top_srcdir)/m4/gpg-error.m4 $(top_srcdir)/m4/iconv.m4 \
+ $(top_srcdir)/m4/libassuan.m4 $(top_srcdir)/m4/pkg.m4 \
+ $(top_srcdir)/m4/qt.m4 $(top_srcdir)/m4/qt4.m4 \
+ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+AR = ar
+ARFLAGS = cru
+AM_V_AR = $(am__v_AR_@AM_V@)
+am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@)
+am__v_AR_0 = @echo " AR " $@;
+am__v_AR_1 =
+libpinentry_curses_a_AR = $(AR) $(ARFLAGS)
+libpinentry_curses_a_LIBADD =
+am_libpinentry_curses_a_OBJECTS = \
+ libpinentry_curses_a-pinentry-curses.$(OBJEXT)
+libpinentry_curses_a_OBJECTS = $(am_libpinentry_curses_a_OBJECTS)
+libpinentry_a_AR = $(AR) $(ARFLAGS)
+libpinentry_a_LIBADD =
+am__libpinentry_a_SOURCES_DIST = pinentry.h pinentry.c argparse.c \
+ argparse.h password-cache.h password-cache.c pinentry-emacs.h \
+ pinentry-emacs.c
+@BUILD_LIBPINENTRY_EMACS_TRUE@am__objects_1 = \
+@BUILD_LIBPINENTRY_EMACS_TRUE@ pinentry-emacs.$(OBJEXT)
+am_libpinentry_a_OBJECTS = pinentry.$(OBJEXT) argparse.$(OBJEXT) \
+ password-cache.$(OBJEXT) $(am__objects_1)
+libpinentry_a_OBJECTS = $(am_libpinentry_a_OBJECTS)
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/argparse.Po \
+ ./$(DEPDIR)/libpinentry_curses_a-pinentry-curses.Po \
+ ./$(DEPDIR)/password-cache.Po ./$(DEPDIR)/pinentry-emacs.Po \
+ ./$(DEPDIR)/pinentry.Po
+am__mv = mv -f
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(libpinentry_curses_a_SOURCES) $(libpinentry_a_SOURCES)
+DIST_SOURCES = $(libpinentry_curses_a_SOURCES) \
+ $(am__libpinentry_a_SOURCES_DIST)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__DIST_COMMON = $(srcdir)/Makefile.in \
+ $(top_srcdir)/build-aux/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+COMMON_CFLAGS = @COMMON_CFLAGS@
+COMMON_LIBS = @COMMON_LIBS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EFL_CFLAGS = @EFL_CFLAGS@
+EFL_LIBS = @EFL_LIBS@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FLTKCFLAGS = @FLTKCFLAGS@
+FLTKCXXFLAGS = @FLTKCXXFLAGS@
+FLTKLIBS = @FLTKLIBS@
+FLTK_CONFIG = @FLTK_CONFIG@
+GITLOG_TO_CHANGELOG = @GITLOG_TO_CHANGELOG@
+GNOME3_CFLAGS = @GNOME3_CFLAGS@
+GNOME3_LIBS = @GNOME3_LIBS@
+GPGRT_CONFIG = @GPGRT_CONFIG@
+GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@
+GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@
+GPG_ERROR_LIBS = @GPG_ERROR_LIBS@
+GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@
+GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@
+GREP = @GREP@
+GTK2_CFLAGS = @GTK2_CFLAGS@
+GTK2_LIBS = @GTK2_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+KF5WAYLANDCLIENT_CFLAGS = @KF5WAYLANDCLIENT_CFLAGS@
+KF5WAYLANDCLIENT_LIBS = @KF5WAYLANDCLIENT_LIBS@
+LDFLAGS = @LDFLAGS@
+LIBASSUAN_CFLAGS = @LIBASSUAN_CFLAGS@
+LIBASSUAN_CONFIG = @LIBASSUAN_CONFIG@
+LIBASSUAN_LIBS = @LIBASSUAN_LIBS@
+LIBCURSES = @LIBCURSES@
+LIBICONV = @LIBICONV@
+LIBNCURSES = @LIBNCURSES@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBSECRET_CFLAGS = @LIBSECRET_CFLAGS@
+LIBSECRET_LIBS = @LIBSECRET_LIBS@
+LIBTERMCAP = @LIBTERMCAP@
+LIBX11_CFLAGS = @LIBX11_CFLAGS@
+LIBX11_LIBS = @LIBX11_LIBS@
+LN_S = @LN_S@
+LTLIBICONV = @LTLIBICONV@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MOC = @MOC@
+MOC2 = @MOC2@
+MOC4 = @MOC4@
+MOC42 = @MOC42@
+NCURSES_CFLAGS = @NCURSES_CFLAGS@
+NCURSES_INCLUDE = @NCURSES_INCLUDE@
+NCURSES_LIBS = @NCURSES_LIBS@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PINENTRY_DEFAULT = @PINENTRY_DEFAULT@
+PINENTRY_QT4_CFLAGS = @PINENTRY_QT4_CFLAGS@
+PINENTRY_QT4_LDFLAGS = @PINENTRY_QT4_LDFLAGS@
+PINENTRY_QT4_LIBS = @PINENTRY_QT4_LIBS@
+PINENTRY_QT_CFLAGS = @PINENTRY_QT_CFLAGS@
+PINENTRY_QT_LDFLAGS = @PINENTRY_QT_LDFLAGS@
+PINENTRY_QT_LIBS = @PINENTRY_QT_LIBS@
+PINENTRY_QT_REQUIRE_CPP11_CFLAGS = @PINENTRY_QT_REQUIRE_CPP11_CFLAGS@
+PINENTRY_QT_REQUIRE_CPP11_LIBS = @PINENTRY_QT_REQUIRE_CPP11_LIBS@
+PINENTRY_QT_X11_EXTRAS_CFLAGS = @PINENTRY_QT_X11_EXTRAS_CFLAGS@
+PINENTRY_QT_X11_EXTRAS_LIBS = @PINENTRY_QT_X11_EXTRAS_LIBS@
+PINENTRY_TQT_CFLAGS = @PINENTRY_TQT_CFLAGS@
+PINENTRY_TQT_LIBS = @PINENTRY_TQT_LIBS@
+PKG_CONFIG = @PKG_CONFIG@
+QTCHOOSER = @QTCHOOSER@
+RANLIB = @RANLIB@
+RCC = @RCC@
+RCC2 = @RCC2@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TQT_MOC = @TQT_MOC@
+VERSION = @VERSION@
+WINDRES = @WINDRES@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+EXTRA_DIST =
+@BUILD_LIBPINENTRY_CURSES_FALSE@pinentry_curses =
+@BUILD_LIBPINENTRY_CURSES_TRUE@pinentry_curses = libpinentry-curses.a
+@BUILD_LIBPINENTRY_EMACS_FALSE@pinentry_emacs_sources =
+@BUILD_LIBPINENTRY_EMACS_TRUE@pinentry_emacs_sources = pinentry-emacs.h pinentry-emacs.c
+noinst_LIBRARIES = libpinentry.a $(pinentry_curses)
+LDADD = $(COMMON_LIBS)
+AM_CPPFLAGS = $(COMMON_CFLAGS) -I$(top_srcdir)/secmem
+libpinentry_a_SOURCES = pinentry.h pinentry.c argparse.c argparse.h \
+ password-cache.h password-cache.c $(pinentry_emacs_sources)
+
+libpinentry_curses_a_SOURCES = pinentry-curses.h pinentry-curses.c
+libpinentry_curses_a_CFLAGS = @NCURSES_CFLAGS@
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu pinentry/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu pinentry/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+libpinentry-curses.a: $(libpinentry_curses_a_OBJECTS) $(libpinentry_curses_a_DEPENDENCIES) $(EXTRA_libpinentry_curses_a_DEPENDENCIES)
+ $(AM_V_at)-rm -f libpinentry-curses.a
+ $(AM_V_AR)$(libpinentry_curses_a_AR) libpinentry-curses.a $(libpinentry_curses_a_OBJECTS) $(libpinentry_curses_a_LIBADD)
+ $(AM_V_at)$(RANLIB) libpinentry-curses.a
+
+libpinentry.a: $(libpinentry_a_OBJECTS) $(libpinentry_a_DEPENDENCIES) $(EXTRA_libpinentry_a_DEPENDENCIES)
+ $(AM_V_at)-rm -f libpinentry.a
+ $(AM_V_AR)$(libpinentry_a_AR) libpinentry.a $(libpinentry_a_OBJECTS) $(libpinentry_a_LIBADD)
+ $(AM_V_at)$(RANLIB) libpinentry.a
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/argparse.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpinentry_curses_a-pinentry-curses.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/password-cache.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pinentry-emacs.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pinentry.Po@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+libpinentry_curses_a-pinentry-curses.o: pinentry-curses.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpinentry_curses_a_CFLAGS) $(CFLAGS) -MT libpinentry_curses_a-pinentry-curses.o -MD -MP -MF $(DEPDIR)/libpinentry_curses_a-pinentry-curses.Tpo -c -o libpinentry_curses_a-pinentry-curses.o `test -f 'pinentry-curses.c' || echo '$(srcdir)/'`pinentry-curses.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpinentry_curses_a-pinentry-curses.Tpo $(DEPDIR)/libpinentry_curses_a-pinentry-curses.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pinentry-curses.c' object='libpinentry_curses_a-pinentry-curses.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpinentry_curses_a_CFLAGS) $(CFLAGS) -c -o libpinentry_curses_a-pinentry-curses.o `test -f 'pinentry-curses.c' || echo '$(srcdir)/'`pinentry-curses.c
+
+libpinentry_curses_a-pinentry-curses.obj: pinentry-curses.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpinentry_curses_a_CFLAGS) $(CFLAGS) -MT libpinentry_curses_a-pinentry-curses.obj -MD -MP -MF $(DEPDIR)/libpinentry_curses_a-pinentry-curses.Tpo -c -o libpinentry_curses_a-pinentry-curses.obj `if test -f 'pinentry-curses.c'; then $(CYGPATH_W) 'pinentry-curses.c'; else $(CYGPATH_W) '$(srcdir)/pinentry-curses.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpinentry_curses_a-pinentry-curses.Tpo $(DEPDIR)/libpinentry_curses_a-pinentry-curses.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pinentry-curses.c' object='libpinentry_curses_a-pinentry-curses.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpinentry_curses_a_CFLAGS) $(CFLAGS) -c -o libpinentry_curses_a-pinentry-curses.obj `if test -f 'pinentry-curses.c'; then $(CYGPATH_W) 'pinentry-curses.c'; else $(CYGPATH_W) '$(srcdir)/pinentry-curses.c'; fi`
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LIBRARIES)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/argparse.Po
+ -rm -f ./$(DEPDIR)/libpinentry_curses_a-pinentry-curses.Po
+ -rm -f ./$(DEPDIR)/password-cache.Po
+ -rm -f ./$(DEPDIR)/pinentry-emacs.Po
+ -rm -f ./$(DEPDIR)/pinentry.Po
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f ./$(DEPDIR)/argparse.Po
+ -rm -f ./$(DEPDIR)/libpinentry_curses_a-pinentry-curses.Po
+ -rm -f ./$(DEPDIR)/password-cache.Po
+ -rm -f ./$(DEPDIR)/pinentry-emacs.Po
+ -rm -f ./$(DEPDIR)/pinentry.Po
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-noinstLIBRARIES cscopelist-am ctags \
+ ctags-am distclean distclean-compile distclean-generic \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \
+ tags tags-am uninstall uninstall-am
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/argparse.c b/debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/argparse.c
new file mode 100644
index 00000000..ee9c08b9
--- /dev/null
+++ b/debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/argparse.c
@@ -0,0 +1,1608 @@
+/* [argparse.c wk 17.06.97] Argument Parser for option handling
+ * Copyright (C) 1998-2001, 2006-2008, 2012 Free Software Foundation, Inc.
+ * Copyright (C) 1997-2001, 2006-2008, 2013-2015 Werner Koch
+ *
+ * This file is part of JNLIB, which is a subsystem of GnuPG.
+ *
+ * JNLIB is free software; you can redistribute it and/or modify it
+ * under the terms of either
+ *
+ * - the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * or
+ *
+ * - 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.
+ *
+ * or both in parallel, as here.
+ *
+ * JNLIB 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 copies of the GNU General Public License
+ * and the GNU Lesser General Public License along with this program;
+ * if not, see <https://www.gnu.org/licenses/>.
+ * SPDX-License-Identifier: (GPL-2.0+ OR LGPL-3.0+)
+ */
+
+/* This file may be used as part of GnuPG or standalone. A GnuPG
+ build is detected by the presence of the macro GNUPG_MAJOR_VERSION.
+ Some feature are only availalbe in the GnuPG build mode.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdarg.h>
+#include <limits.h>
+#include <errno.h>
+
+#ifdef GNUPG_MAJOR_VERSION
+# include "libjnlib-config.h"
+# include "mischelp.h"
+# include "stringhelp.h"
+# include "logging.h"
+# ifdef JNLIB_NEED_UTF8CONV
+# include "utf8conv.h"
+# endif
+#endif /*GNUPG_MAJOR_VERSION*/
+
+#include "argparse.h"
+
+/* GnuPG uses GPLv3+ but a standalone version of this defaults to
+ GPLv2+ because that is the license of this file. Change this if
+ you include it in a program which uses GPLv3. If you don't want to
+ set a a copyright string for your usage() you may also hardcode it
+ here. */
+#ifndef GNUPG_MAJOR_VERSION
+
+# define ARGPARSE_GPL_VERSION 2
+# define ARGPARSE_CRIGHT_STR "Copyright (C) YEAR NAME"
+
+#else /* Used by GnuPG */
+
+# define ARGPARSE_GPL_VERSION 3
+# define ARGPARSE_CRIGHT_STR "Copyright (C) 2015 Free Software Foundation, Inc."
+
+#endif /*GNUPG_MAJOR_VERSION*/
+
+/* Replacements for standalone builds. */
+#ifndef GNUPG_MAJOR_VERSION
+# ifndef _
+# define _(a) (a)
+# endif
+# ifndef DIM
+# define DIM(v) (sizeof(v)/sizeof((v)[0]))
+# endif
+# define jnlib_malloc(a) malloc ((a))
+# define jnlib_realloc(a,b) realloc ((a), (b))
+# define jnlib_strdup(a) strdup ((a))
+# define jnlib_free(a) free ((a))
+# define jnlib_log_error my_log_error
+# define jnlib_log_bug my_log_bug
+# define trim_spaces(a) my_trim_spaces ((a))
+# define map_static_macro_string(a) (a)
+#endif /*!GNUPG_MAJOR_VERSION*/
+
+
+#define ARGPARSE_STR(v) #v
+#define ARGPARSE_STR2(v) ARGPARSE_STR(v)
+
+
+/* Replacements for standalone builds. */
+#ifndef GNUPG_MAJOR_VERSION
+static void
+my_log_error (const char *fmt, ...)
+{
+ va_list arg_ptr ;
+
+ va_start (arg_ptr, fmt);
+ fprintf (stderr, "%s: ", strusage (11));
+ vfprintf (stderr, fmt, arg_ptr);
+ va_end (arg_ptr);
+}
+
+static void
+my_log_bug (const char *fmt, ...)
+{
+ va_list arg_ptr ;
+
+ va_start (arg_ptr, fmt);
+ fprintf (stderr, "%s: Ohhhh jeeee: ", strusage (11));
+ vfprintf (stderr, fmt, arg_ptr);
+ va_end (arg_ptr);
+ abort ();
+}
+
+static char *
+my_trim_spaces (char *str)
+{
+ char *string, *p, *mark;
+
+ string = str;
+ /* Find first non space character. */
+ for (p=string; *p && isspace (*(unsigned char*)p) ; p++)
+ ;
+ /* Move characters. */
+ for ((mark = NULL); (*string = *p); string++, p++)
+ if (isspace (*(unsigned char*)p))
+ {
+ if (!mark)
+ mark = string;
+ }
+ else
+ mark = NULL;
+ if (mark)
+ *mark = '\0' ; /* Remove trailing spaces. */
+
+ return str ;
+}
+
+#endif /*!GNUPG_MAJOR_VERSION*/
+
+
+
+/*********************************
+ * @Summary arg_parse
+ * #include "argparse.h"
+ *
+ * typedef struct {
+ * char *argc; pointer to argc (value subject to change)
+ * char ***argv; pointer to argv (value subject to change)
+ * unsigned flags; Global flags (DO NOT CHANGE)
+ * int err; print error about last option
+ * 1 = warning, 2 = abort
+ * int r_opt; return option
+ * int r_type; type of return value (0 = no argument found)
+ * union {
+ * int ret_int;
+ * long ret_long
+ * ulong ret_ulong;
+ * char *ret_str;
+ * } r; Return values
+ * struct {
+ * int idx;
+ * const char *last;
+ * void *aliases;
+ * } internal; DO NOT CHANGE
+ * } ARGPARSE_ARGS;
+ *
+ * typedef struct {
+ * int short_opt;
+ * const char *long_opt;
+ * unsigned flags;
+ * } ARGPARSE_OPTS;
+ *
+ * int arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts );
+ *
+ * @Description
+ * This is my replacement for getopt(). See the example for a typical usage.
+ * Global flags are:
+ * Bit 0 : Do not remove options form argv
+ * Bit 1 : Do not stop at last option but return other args
+ * with r_opt set to -1.
+ * Bit 2 : Assume options and real args are mixed.
+ * Bit 3 : Do not use -- to stop option processing.
+ * Bit 4 : Do not skip the first arg.
+ * Bit 5 : allow usage of long option with only one dash
+ * Bit 6 : ignore --version
+ * all other bits must be set to zero, this value is modified by the
+ * function, so assume this is write only.
+ * Local flags (for each option):
+ * Bit 2-0 : 0 = does not take an argument
+ * 1 = takes int argument
+ * 2 = takes string argument
+ * 3 = takes long argument
+ * 4 = takes ulong argument
+ * Bit 3 : argument is optional (r_type will the be set to 0)
+ * Bit 4 : allow 0x etc. prefixed values.
+ * Bit 6 : Ignore this option
+ * Bit 7 : This is a command and not an option
+ * You stop the option processing by setting opts to NULL, the function will
+ * then return 0.
+ * @Return Value
+ * Returns the args.r_opt or 0 if ready
+ * r_opt may be -2/-7 to indicate an unknown option/command.
+ * @See Also
+ * ArgExpand
+ * @Notes
+ * You do not need to process the options 'h', '--help' or '--version'
+ * because this function includes standard help processing; but if you
+ * specify '-h', '--help' or '--version' you have to do it yourself.
+ * The option '--' stops argument processing; if bit 1 is set the function
+ * continues to return normal arguments.
+ * To process float args or unsigned args you must use a string args and do
+ * the conversion yourself.
+ * @Example
+ *
+ * ARGPARSE_OPTS opts[] = {
+ * { 'v', "verbose", 0 },
+ * { 'd', "debug", 0 },
+ * { 'o', "output", 2 },
+ * { 'c', "cross-ref", 2|8 },
+ * { 'm', "my-option", 1|8 },
+ * { 300, "ignored-long-option, ARGPARSE_OP_IGNORE},
+ * { 500, "have-no-short-option-for-this-long-option", 0 },
+ * {0} };
+ * ARGPARSE_ARGS pargs = { &argc, &argv, 0 }
+ *
+ * while( ArgParse( &pargs, &opts) ) {
+ * switch( pargs.r_opt ) {
+ * case 'v': opt.verbose++; break;
+ * case 'd': opt.debug++; break;
+ * case 'o': opt.outfile = pargs.r.ret_str; break;
+ * case 'c': opt.crf = pargs.r_type? pargs.r.ret_str:"a.crf"; break;
+ * case 'm': opt.myopt = pargs.r_type? pargs.r.ret_int : 1; break;
+ * case 500: opt.a_long_one++; break
+ * default : pargs.err = 1; break; -- force warning output --
+ * }
+ * }
+ * if( argc > 1 )
+ * log_fatal( "Too many args");
+ *
+ */
+
+typedef struct alias_def_s *ALIAS_DEF;
+struct alias_def_s {
+ ALIAS_DEF next;
+ char *name; /* malloced buffer with name, \0, value */
+ const char *value; /* ptr into name */
+};
+
+
+/* Object to store the names for the --ignore-invalid-option option.
+ This is a simple linked list. */
+typedef struct iio_item_def_s *IIO_ITEM_DEF;
+struct iio_item_def_s
+{
+ IIO_ITEM_DEF next;
+ char name[1]; /* String with the long option name. */
+};
+
+static const char *(*strusage_handler)( int ) = NULL;
+static int (*custom_outfnc) (int, const char *);
+
+static int set_opt_arg(ARGPARSE_ARGS *arg, unsigned flags, char *s);
+static void show_help(ARGPARSE_OPTS *opts, unsigned flags);
+static void show_version(void);
+static int writestrings (int is_error, const char *string, ...)
+#if __GNUC__ >= 4
+ __attribute__ ((sentinel(0)))
+#endif
+ ;
+
+
+void
+argparse_register_outfnc (int (*fnc)(int, const char *))
+{
+ custom_outfnc = fnc;
+}
+
+
+/* Write STRING and all following const char * arguments either to
+ stdout or, if IS_ERROR is set, to stderr. The list of strings must
+ be terminated by a NULL. */
+static int
+writestrings (int is_error, const char *string, ...)
+{
+ va_list arg_ptr;
+ const char *s;
+ int count = 0;
+
+ if (string)
+ {
+ s = string;
+ va_start (arg_ptr, string);
+ do
+ {
+ if (custom_outfnc)
+ custom_outfnc (is_error? 2:1, s);
+ else
+ fputs (s, is_error? stderr : stdout);
+ count += strlen (s);
+ }
+ while ((s = va_arg (arg_ptr, const char *)));
+ va_end (arg_ptr);
+ }
+ return count;
+}
+
+
+static void
+flushstrings (int is_error)
+{
+ if (custom_outfnc)
+ custom_outfnc (is_error? 2:1, NULL);
+ else
+ fflush (is_error? stderr : stdout);
+}
+
+
+static void
+initialize( ARGPARSE_ARGS *arg, const char *filename, unsigned *lineno )
+{
+ if( !(arg->flags & (1<<15)) )
+ {
+ /* Initialize this instance. */
+ arg->internal.idx = 0;
+ arg->internal.last = NULL;
+ arg->internal.inarg = 0;
+ arg->internal.stopped = 0;
+ arg->internal.aliases = NULL;
+ arg->internal.cur_alias = NULL;
+ arg->internal.iio_list = NULL;
+ arg->err = 0;
+ arg->flags |= 1<<15; /* Mark as initialized. */
+ if ( *arg->argc < 0 )
+ jnlib_log_bug ("invalid argument for arg_parse\n");
+ }
+
+
+ if (arg->err)
+ {
+ /* Last option was erroneous. */
+ const char *s;
+
+ if (filename)
+ {
+ if ( arg->r_opt == ARGPARSE_UNEXPECTED_ARG )
+ s = _("argument not expected");
+ else if ( arg->r_opt == ARGPARSE_READ_ERROR )
+ s = _("read error");
+ else if ( arg->r_opt == ARGPARSE_KEYWORD_TOO_LONG )
+ s = _("keyword too long");
+ else if ( arg->r_opt == ARGPARSE_MISSING_ARG )
+ s = _("missing argument");
+ else if ( arg->r_opt == ARGPARSE_INVALID_ARG )
+ s = _("invalid argument");
+ else if ( arg->r_opt == ARGPARSE_INVALID_COMMAND )
+ s = _("invalid command");
+ else if ( arg->r_opt == ARGPARSE_INVALID_ALIAS )
+ s = _("invalid alias definition");
+ else if ( arg->r_opt == ARGPARSE_OUT_OF_CORE )
+ s = _("out of core");
+ else
+ s = _("invalid option");
+ jnlib_log_error ("%s:%u: %s\n", filename, *lineno, s);
+ }
+ else
+ {
+ s = arg->internal.last? arg->internal.last:"[??]";
+
+ if ( arg->r_opt == ARGPARSE_MISSING_ARG )
+ jnlib_log_error (_("missing argument for option \"%.50s\"\n"), s);
+ else if ( arg->r_opt == ARGPARSE_INVALID_ARG )
+ jnlib_log_error (_("invalid argument for option \"%.50s\"\n"), s);
+ else if ( arg->r_opt == ARGPARSE_UNEXPECTED_ARG )
+ jnlib_log_error (_("option \"%.50s\" does not expect an "
+ "argument\n"), s );
+ else if ( arg->r_opt == ARGPARSE_INVALID_COMMAND )
+ jnlib_log_error (_("invalid command \"%.50s\"\n"), s);
+ else if ( arg->r_opt == ARGPARSE_AMBIGUOUS_OPTION )
+ jnlib_log_error (_("option \"%.50s\" is ambiguous\n"), s);
+ else if ( arg->r_opt == ARGPARSE_AMBIGUOUS_COMMAND )
+ jnlib_log_error (_("command \"%.50s\" is ambiguous\n"),s );
+ else if ( arg->r_opt == ARGPARSE_OUT_OF_CORE )
+ jnlib_log_error ("%s\n", _("out of core\n"));
+ else
+ jnlib_log_error (_("invalid option \"%.50s\"\n"), s);
+ }
+ if (arg->err != ARGPARSE_PRINT_WARNING)
+ exit (2);
+ arg->err = 0;
+ }
+
+ /* Zero out the return value union. */
+ arg->r.ret_str = NULL;
+ arg->r.ret_long = 0;
+}
+
+
+static void
+store_alias( ARGPARSE_ARGS *arg, char *name, char *value )
+{
+ /* TODO: replace this dummy function with a rea one
+ * and fix the probelms IRIX has with (ALIAS_DEV)arg..
+ * used as lvalue
+ */
+ (void)arg;
+ (void)name;
+ (void)value;
+#if 0
+ ALIAS_DEF a = jnlib_xmalloc( sizeof *a );
+ a->name = name;
+ a->value = value;
+ a->next = (ALIAS_DEF)arg->internal.aliases;
+ (ALIAS_DEF)arg->internal.aliases = a;
+#endif
+}
+
+
+/* Return true if KEYWORD is in the ignore-invalid-option list. */
+static int
+ignore_invalid_option_p (ARGPARSE_ARGS *arg, const char *keyword)
+{
+ IIO_ITEM_DEF item = arg->internal.iio_list;
+
+ for (; item; item = item->next)
+ if (!strcmp (item->name, keyword))
+ return 1;
+ return 0;
+}
+
+
+/* Add the keywords up to the next LF to the list of to be ignored
+ options. After returning FP will either be at EOF or the next
+ character read wll be the first of a new line. The function
+ returns 0 on success or true on malloc failure. */
+static int
+ignore_invalid_option_add (ARGPARSE_ARGS *arg, FILE *fp)
+{
+ IIO_ITEM_DEF item;
+ int c;
+ char name[100];
+ int namelen = 0;
+ int ready = 0;
+ enum { skipWS, collectNAME, skipNAME, addNAME} state = skipWS;
+
+ while (!ready)
+ {
+ c = getc (fp);
+ if (c == '\n')
+ ready = 1;
+ else if (c == EOF)
+ {
+ c = '\n';
+ ready = 1;
+ }
+ again:
+ switch (state)
+ {
+ case skipWS:
+ if (!isascii (c) || !isspace(c))
+ {
+ namelen = 0;
+ state = collectNAME;
+ goto again;
+ }
+ break;
+
+ case collectNAME:
+ if (isspace (c))
+ {
+ state = addNAME;
+ goto again;
+ }
+ else if (namelen < DIM(name)-1)
+ name[namelen++] = c;
+ else /* Too long. */
+ state = skipNAME;
+ break;
+
+ case skipNAME:
+ if (isspace (c))
+ {
+ state = skipWS;
+ goto again;
+ }
+ break;
+
+ case addNAME:
+ name[namelen] = 0;
+ if (!ignore_invalid_option_p (arg, name))
+ {
+ item = jnlib_malloc (sizeof *item + namelen);
+ if (!item)
+ return 1;
+ strcpy (item->name, name);
+ item->next = (IIO_ITEM_DEF)arg->internal.iio_list;
+ arg->internal.iio_list = item;
+ }
+ state = skipWS;
+ goto again;
+ }
+ }
+ return 0;
+}
+
+
+/* Clear the entire ignore-invalid-option list. */
+static void
+ignore_invalid_option_clear (ARGPARSE_ARGS *arg)
+{
+ IIO_ITEM_DEF item, tmpitem;
+
+ for (item = arg->internal.iio_list; item; item = tmpitem)
+ {
+ tmpitem = item->next;
+ jnlib_free (item);
+ }
+ arg->internal.iio_list = NULL;
+}
+
+
+
+/****************
+ * Get options from a file.
+ * Lines starting with '#' are comment lines.
+ * Syntax is simply a keyword and the argument.
+ * Valid keywords are all keywords from the long_opt list without
+ * the leading dashes. The special keywords "help", "warranty" and "version"
+ * are not valid here.
+ * The special keyword "alias" may be used to store alias definitions,
+ * which are later expanded like long options.
+ * The option
+ * ignore-invalid-option OPTIONNAMEs
+ * is recognized and updates a list of option which should be ignored if they
+ * are not defined.
+ * Caller must free returned strings.
+ * If called with FP set to NULL command line args are parse instead.
+ *
+ * Q: Should we allow the syntax
+ * keyword = value
+ * and accept for boolean options a value of 1/0, yes/no or true/false?
+ * Note: Abbreviation of options is here not allowed.
+ */
+int
+optfile_parse (FILE *fp, const char *filename, unsigned *lineno,
+ ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
+{
+ int state, i, c;
+ int idx=0;
+ char keyword[100];
+ char *buffer = NULL;
+ size_t buflen = 0;
+ int in_alias=0;
+
+ if (!fp) /* Divert to to arg_parse() in this case. */
+ return arg_parse (arg, opts);
+
+ initialize (arg, filename, lineno);
+
+ /* Find the next keyword. */
+ state = i = 0;
+ for (;;)
+ {
+ c = getc (fp);
+ if (c == '\n' || c== EOF )
+ {
+ if ( c != EOF )
+ ++*lineno;
+ if (state == -1)
+ break;
+ else if (state == 2)
+ {
+ keyword[i] = 0;
+ for (i=0; opts[i].short_opt; i++ )
+ {
+ if (opts[i].long_opt && !strcmp (opts[i].long_opt, keyword))
+ break;
+ }
+ idx = i;
+ arg->r_opt = opts[idx].short_opt;
+ if ((opts[idx].flags & ARGPARSE_OPT_IGNORE))
+ {
+ state = i = 0;
+ continue;
+ }
+ else if (!opts[idx].short_opt )
+ {
+ if (!strcmp (keyword, "ignore-invalid-option"))
+ {
+ /* No argument - ignore this meta option. */
+ state = i = 0;
+ continue;
+ }
+ else if (ignore_invalid_option_p (arg, keyword))
+ {
+ /* This invalid option is in the iio list. */
+ state = i = 0;
+ continue;
+ }
+ arg->r_opt = ((opts[idx].flags & ARGPARSE_OPT_COMMAND)
+ ? ARGPARSE_INVALID_COMMAND
+ : ARGPARSE_INVALID_OPTION);
+ }
+ else if (!(opts[idx].flags & ARGPARSE_TYPE_MASK))
+ arg->r_type = 0; /* Does not take an arg. */
+ else if ((opts[idx].flags & ARGPARSE_OPT_OPTIONAL) )
+ arg->r_type = 0; /* Arg is optional. */
+ else
+ arg->r_opt = ARGPARSE_MISSING_ARG;
+
+ break;
+ }
+ else if (state == 3)
+ {
+ /* No argument found. */
+ if (in_alias)
+ arg->r_opt = ARGPARSE_MISSING_ARG;
+ else if (!(opts[idx].flags & ARGPARSE_TYPE_MASK))
+ arg->r_type = 0; /* Does not take an arg. */
+ else if ((opts[idx].flags & ARGPARSE_OPT_OPTIONAL))
+ arg->r_type = 0; /* No optional argument. */
+ else
+ arg->r_opt = ARGPARSE_MISSING_ARG;
+
+ break;
+ }
+ else if (state == 4)
+ {
+ /* Has an argument. */
+ if (in_alias)
+ {
+ if (!buffer)
+ arg->r_opt = ARGPARSE_UNEXPECTED_ARG;
+ else
+ {
+ char *p;
+
+ buffer[i] = 0;
+ p = strpbrk (buffer, " \t");
+ if (p)
+ {
+ *p++ = 0;
+ trim_spaces (p);
+ }
+ if (!p || !*p)
+ {
+ jnlib_free (buffer);
+ arg->r_opt = ARGPARSE_INVALID_ALIAS;
+ }
+ else
+ {
+ store_alias (arg, buffer, p);
+ }
+ }
+ }
+ else if (!(opts[idx].flags & ARGPARSE_TYPE_MASK))
+ arg->r_opt = ARGPARSE_UNEXPECTED_ARG;
+ else
+ {
+ char *p;
+
+ if (!buffer)
+ {
+ keyword[i] = 0;
+ buffer = jnlib_strdup (keyword);
+ if (!buffer)
+ arg->r_opt = ARGPARSE_OUT_OF_CORE;
+ }
+ else
+ buffer[i] = 0;
+
+ if (buffer)
+ {
+ trim_spaces (buffer);
+ p = buffer;
+ if (*p == '"')
+ {
+ /* Remove quotes. */
+ p++;
+ if (*p && p[strlen(p)-1] == '\"' )
+ p[strlen(p)-1] = 0;
+ }
+ if (!set_opt_arg (arg, opts[idx].flags, p))
+ jnlib_free(buffer);
+ }
+ }
+ break;
+ }
+ else if (c == EOF)
+ {
+ ignore_invalid_option_clear (arg);
+ if (ferror (fp))
+ arg->r_opt = ARGPARSE_READ_ERROR;
+ else
+ arg->r_opt = 0; /* EOF. */
+ break;
+ }
+ state = 0;
+ i = 0;
+ }
+ else if (state == -1)
+ ; /* Skip. */
+ else if (state == 0 && isascii (c) && isspace(c))
+ ; /* Skip leading white space. */
+ else if (state == 0 && c == '#' )
+ state = 1; /* Start of a comment. */
+ else if (state == 1)
+ ; /* Skip comments. */
+ else if (state == 2 && isascii (c) && isspace(c))
+ {
+ /* Check keyword. */
+ keyword[i] = 0;
+ for (i=0; opts[i].short_opt; i++ )
+ if (opts[i].long_opt && !strcmp (opts[i].long_opt, keyword))
+ break;
+ idx = i;
+ arg->r_opt = opts[idx].short_opt;
+ if ((opts[idx].flags & ARGPARSE_OPT_IGNORE))
+ {
+ state = 1; /* Process like a comment. */
+ }
+ else if (!opts[idx].short_opt)
+ {
+ if (!strcmp (keyword, "alias"))
+ {
+ in_alias = 1;
+ state = 3;
+ }
+ else if (!strcmp (keyword, "ignore-invalid-option"))
+ {
+ if (ignore_invalid_option_add (arg, fp))
+ {
+ arg->r_opt = ARGPARSE_OUT_OF_CORE;
+ break;
+ }
+ state = i = 0;
+ ++*lineno;
+ }
+ else if (ignore_invalid_option_p (arg, keyword))
+ state = 1; /* Process like a comment. */
+ else
+ {
+ arg->r_opt = ((opts[idx].flags & ARGPARSE_OPT_COMMAND)
+ ? ARGPARSE_INVALID_COMMAND
+ : ARGPARSE_INVALID_OPTION);
+ state = -1; /* Skip rest of line and leave. */
+ }
+ }
+ else
+ state = 3;
+ }
+ else if (state == 3)
+ {
+ /* Skip leading spaces of the argument. */
+ if (!isascii (c) || !isspace(c))
+ {
+ i = 0;
+ keyword[i++] = c;
+ state = 4;
+ }
+ }
+ else if (state == 4)
+ {
+ /* Collect the argument. */
+ if (buffer)
+ {
+ if (i < buflen-1)
+ buffer[i++] = c;
+ else
+ {
+ char *tmp;
+ size_t tmplen = buflen + 50;
+
+ tmp = jnlib_realloc (buffer, tmplen);
+ if (tmp)
+ {
+ buflen = tmplen;
+ buffer = tmp;
+ buffer[i++] = c;
+ }
+ else
+ {
+ jnlib_free (buffer);
+ arg->r_opt = ARGPARSE_OUT_OF_CORE;
+ break;
+ }
+ }
+ }
+ else if (i < DIM(keyword)-1)
+ keyword[i++] = c;
+ else
+ {
+ size_t tmplen = DIM(keyword) + 50;
+ buffer = jnlib_malloc (tmplen);
+ if (buffer)
+ {
+ buflen = tmplen;
+ memcpy(buffer, keyword, i);
+ buffer[i++] = c;
+ }
+ else
+ {
+ arg->r_opt = ARGPARSE_OUT_OF_CORE;
+ break;
+ }
+ }
+ }
+ else if (i >= DIM(keyword)-1)
+ {
+ arg->r_opt = ARGPARSE_KEYWORD_TOO_LONG;
+ state = -1; /* Skip rest of line and leave. */
+ }
+ else
+ {
+ keyword[i++] = c;
+ state = 2;
+ }
+ }
+
+ return arg->r_opt;
+}
+
+
+
+static int
+find_long_option( ARGPARSE_ARGS *arg,
+ ARGPARSE_OPTS *opts, const char *keyword )
+{
+ int i;
+ size_t n;
+
+ (void)arg;
+
+ /* Would be better if we can do a binary search, but it is not
+ possible to reorder our option table because we would mess
+ up our help strings - What we can do is: Build a nice option
+ lookup table when this function is first invoked */
+ if( !*keyword )
+ return -1;
+ for(i=0; opts[i].short_opt; i++ )
+ if( opts[i].long_opt && !strcmp( opts[i].long_opt, keyword) )
+ return i;
+#if 0
+ {
+ ALIAS_DEF a;
+ /* see whether it is an alias */
+ for( a = args->internal.aliases; a; a = a->next ) {
+ if( !strcmp( a->name, keyword) ) {
+ /* todo: must parse the alias here */
+ args->internal.cur_alias = a;
+ return -3; /* alias available */
+ }
+ }
+ }
+#endif
+ /* not found, see whether it is an abbreviation */
+ /* aliases may not be abbreviated */
+ n = strlen( keyword );
+ for(i=0; opts[i].short_opt; i++ ) {
+ if( opts[i].long_opt && !strncmp( opts[i].long_opt, keyword, n ) ) {
+ int j;
+ for(j=i+1; opts[j].short_opt; j++ ) {
+ if( opts[j].long_opt
+ && !strncmp( opts[j].long_opt, keyword, n ) )
+ return -2; /* abbreviation is ambiguous */
+ }
+ return i;
+ }
+ }
+ return -1; /* Not found. */
+}
+
+int
+arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
+{
+ int idx;
+ int argc;
+ char **argv;
+ char *s, *s2;
+ int i;
+
+ initialize( arg, NULL, NULL );
+ argc = *arg->argc;
+ argv = *arg->argv;
+ idx = arg->internal.idx;
+
+ if (!idx && argc && !(arg->flags & ARGPARSE_FLAG_ARG0))
+ {
+ /* Skip the first argument. */
+ argc--; argv++; idx++;
+ }
+
+ next_one:
+ if (!argc)
+ {
+ /* No more args. */
+ arg->r_opt = 0;
+ goto leave; /* Ready. */
+ }
+
+ s = *argv;
+ arg->internal.last = s;
+
+ if (arg->internal.stopped && (arg->flags & ARGPARSE_FLAG_ALL))
+ {
+ arg->r_opt = ARGPARSE_IS_ARG; /* Not an option but an argument. */
+ arg->r_type = 2;
+ arg->r.ret_str = s;
+ argc--; argv++; idx++; /* set to next one */
+ }
+ else if( arg->internal.stopped )
+ {
+ arg->r_opt = 0;
+ goto leave; /* Ready. */
+ }
+ else if ( *s == '-' && s[1] == '-' )
+ {
+ /* Long option. */
+ char *argpos;
+
+ arg->internal.inarg = 0;
+ if (!s[2] && !(arg->flags & ARGPARSE_FLAG_NOSTOP))
+ {
+ /* Stop option processing. */
+ arg->internal.stopped = 1;
+ arg->flags |= ARGPARSE_FLAG_STOP_SEEN;
+ argc--; argv++; idx++;
+ goto next_one;
+ }
+
+ argpos = strchr( s+2, '=' );
+ if ( argpos )
+ *argpos = 0;
+ i = find_long_option ( arg, opts, s+2 );
+ if ( argpos )
+ *argpos = '=';
+
+ if ( i < 0 && !strcmp ( "help", s+2) )
+ show_help (opts, arg->flags);
+ else if ( i < 0 && !strcmp ( "version", s+2) )
+ {
+ if (!(arg->flags & ARGPARSE_FLAG_NOVERSION))
+ {
+ show_version ();
+ exit(0);
+ }
+ }
+ else if ( i < 0 && !strcmp( "warranty", s+2))
+ {
+ writestrings (0, strusage (16), "\n", NULL);
+ exit (0);
+ }
+ else if ( i < 0 && !strcmp( "dump-options", s+2) )
+ {
+ for (i=0; opts[i].short_opt; i++ )
+ {
+ if (opts[i].long_opt && !(opts[i].flags & ARGPARSE_OPT_IGNORE))
+ writestrings (0, "--", opts[i].long_opt, "\n", NULL);
+ }
+ writestrings (0, "--dump-options\n--help\n--version\n--warranty\n",
+ NULL);
+ exit (0);
+ }
+
+ if ( i == -2 )
+ arg->r_opt = ARGPARSE_AMBIGUOUS_OPTION;
+ else if ( i == -1 )
+ {
+ arg->r_opt = ARGPARSE_INVALID_OPTION;
+ arg->r.ret_str = s+2;
+ }
+ else
+ arg->r_opt = opts[i].short_opt;
+ if ( i < 0 )
+ ;
+ else if ( (opts[i].flags & ARGPARSE_TYPE_MASK) )
+ {
+ if ( argpos )
+ {
+ s2 = argpos+1;
+ if ( !*s2 )
+ s2 = NULL;
+ }
+ else
+ s2 = argv[1];
+ if ( !s2 && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) )
+ {
+ arg->r_type = ARGPARSE_TYPE_NONE; /* Argument is optional. */
+ }
+ else if ( !s2 )
+ {
+ arg->r_opt = ARGPARSE_MISSING_ARG;
+ }
+ else if ( !argpos && *s2 == '-'
+ && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) )
+ {
+ /* The argument is optional and the next seems to be an
+ option. We do not check this possible option but
+ assume no argument */
+ arg->r_type = ARGPARSE_TYPE_NONE;
+ }
+ else
+ {
+ set_opt_arg (arg, opts[i].flags, s2);
+ if ( !argpos )
+ {
+ argc--; argv++; idx++; /* Skip one. */
+ }
+ }
+ }
+ else
+ {
+ /* Does not take an argument. */
+ if ( argpos )
+ arg->r_type = ARGPARSE_UNEXPECTED_ARG;
+ else
+ arg->r_type = 0;
+ }
+ argc--; argv++; idx++; /* Set to next one. */
+ }
+ else if ( (*s == '-' && s[1]) || arg->internal.inarg )
+ {
+ /* Short option. */
+ int dash_kludge = 0;
+
+ i = 0;
+ if ( !arg->internal.inarg )
+ {
+ arg->internal.inarg++;
+ if ( (arg->flags & ARGPARSE_FLAG_ONEDASH) )
+ {
+ for (i=0; opts[i].short_opt; i++ )
+ if ( opts[i].long_opt && !strcmp (opts[i].long_opt, s+1))
+ {
+ dash_kludge = 1;
+ break;
+ }
+ }
+ }
+ s += arg->internal.inarg;
+
+ if (!dash_kludge )
+ {
+ for (i=0; opts[i].short_opt; i++ )
+ if ( opts[i].short_opt == *s )
+ break;
+ }
+
+ if ( !opts[i].short_opt && ( *s == 'h' || *s == '?' ) )
+ show_help (opts, arg->flags);
+
+ arg->r_opt = opts[i].short_opt;
+ if (!opts[i].short_opt )
+ {
+ arg->r_opt = (opts[i].flags & ARGPARSE_OPT_COMMAND)?
+ ARGPARSE_INVALID_COMMAND:ARGPARSE_INVALID_OPTION;
+ arg->internal.inarg++; /* Point to the next arg. */
+ arg->r.ret_str = s;
+ }
+ else if ( (opts[i].flags & ARGPARSE_TYPE_MASK) )
+ {
+ if ( s[1] && !dash_kludge )
+ {
+ s2 = s+1;
+ set_opt_arg (arg, opts[i].flags, s2);
+ }
+ else
+ {
+ s2 = argv[1];
+ if ( !s2 && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) )
+ {
+ arg->r_type = ARGPARSE_TYPE_NONE;
+ }
+ else if ( !s2 )
+ {
+ arg->r_opt = ARGPARSE_MISSING_ARG;
+ }
+ else if ( *s2 == '-' && s2[1]
+ && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) )
+ {
+ /* The argument is optional and the next seems to
+ be an option. We do not check this possible
+ option but assume no argument. */
+ arg->r_type = ARGPARSE_TYPE_NONE;
+ }
+ else
+ {
+ set_opt_arg (arg, opts[i].flags, s2);
+ argc--; argv++; idx++; /* Skip one. */
+ }
+ }
+ s = "x"; /* This is so that !s[1] yields false. */
+ }
+ else
+ {
+ /* Does not take an argument. */
+ arg->r_type = ARGPARSE_TYPE_NONE;
+ arg->internal.inarg++; /* Point to the next arg. */
+ }
+ if ( !s[1] || dash_kludge )
+ {
+ /* No more concatenated short options. */
+ arg->internal.inarg = 0;
+ argc--; argv++; idx++;
+ }
+ }
+ else if ( arg->flags & ARGPARSE_FLAG_MIXED )
+ {
+ arg->r_opt = ARGPARSE_IS_ARG;
+ arg->r_type = 2;
+ arg->r.ret_str = s;
+ argc--; argv++; idx++; /* Set to next one. */
+ }
+ else
+ {
+ arg->internal.stopped = 1; /* Stop option processing. */
+ goto next_one;
+ }
+
+ leave:
+ *arg->argc = argc;
+ *arg->argv = argv;
+ arg->internal.idx = idx;
+ return arg->r_opt;
+}
+
+
+/* Returns: -1 on error, 0 for an integer type and 1 for a non integer
+ type argument. */
+static int
+set_opt_arg (ARGPARSE_ARGS *arg, unsigned flags, char *s)
+{
+ int base = (flags & ARGPARSE_OPT_PREFIX)? 0 : 10;
+ long l;
+
+ switch ( (arg->r_type = (flags & ARGPARSE_TYPE_MASK)) )
+ {
+ case ARGPARSE_TYPE_LONG:
+ case ARGPARSE_TYPE_INT:
+ errno = 0;
+ l = strtol (s, NULL, base);
+ if ((l == LONG_MIN || l == LONG_MAX) && errno == ERANGE)
+ {
+ arg->r_opt = ARGPARSE_INVALID_ARG;
+ return -1;
+ }
+ if (arg->r_type == ARGPARSE_TYPE_LONG)
+ arg->r.ret_long = l;
+ else if ( (l < 0 && l < INT_MIN) || l > INT_MAX )
+ {
+ arg->r_opt = ARGPARSE_INVALID_ARG;
+ return -1;
+ }
+ else
+ arg->r.ret_int = (int)l;
+ return 0;
+
+ case ARGPARSE_TYPE_ULONG:
+ while (isascii (*s) && isspace(*s))
+ s++;
+ if (*s == '-')
+ {
+ arg->r.ret_ulong = 0;
+ arg->r_opt = ARGPARSE_INVALID_ARG;
+ return -1;
+ }
+ errno = 0;
+ arg->r.ret_ulong = strtoul (s, NULL, base);
+ if (arg->r.ret_ulong == ULONG_MAX && errno == ERANGE)
+ {
+ arg->r_opt = ARGPARSE_INVALID_ARG;
+ return -1;
+ }
+ return 0;
+
+ case ARGPARSE_TYPE_STRING:
+ default:
+ arg->r.ret_str = s;
+ return 1;
+ }
+}
+
+
+static size_t
+long_opt_strlen( ARGPARSE_OPTS *o )
+{
+ size_t n = strlen (o->long_opt);
+
+ if ( o->description && *o->description == '|' )
+ {
+ const char *s;
+#ifdef JNLIB_NEED_UTF8CONV
+ int is_utf8 = is_native_utf8 ();
+#endif
+
+ s=o->description+1;
+ if ( *s != '=' )
+ n++;
+ /* For a (mostly) correct length calculation we exclude
+ continuation bytes (10xxxxxx) if we are on a native utf8
+ terminal. */
+ for (; *s && *s != '|'; s++ )
+#ifdef JNLIB_NEED_UTF8CONV
+ if ( is_utf8 && (*s&0xc0) != 0x80 )
+#endif
+ n++;
+ }
+ return n;
+}
+
+
+/****************
+ * Print formatted help. The description string has some special
+ * meanings:
+ * - A description string which is "@" suppresses help output for
+ * this option
+ * - a description,ine which starts with a '@' and is followed by
+ * any other characters is printed as is; this may be used for examples
+ * ans such.
+ * - A description which starts with a '|' outputs the string between this
+ * bar and the next one as arguments of the long option.
+ */
+static void
+show_help (ARGPARSE_OPTS *opts, unsigned int flags)
+{
+ const char *s;
+ char tmp[2];
+
+ show_version ();
+ writestrings (0, "\n", NULL);
+ s = strusage (42);
+ if (s && *s == '1')
+ {
+ s = strusage (40);
+ writestrings (1, s, NULL);
+ if (*s && s[strlen(s)] != '\n')
+ writestrings (1, "\n", NULL);
+ }
+ s = strusage(41);
+ writestrings (0, s, "\n", NULL);
+ if ( opts[0].description )
+ {
+ /* Auto format the option description. */
+ int i,j, indent;
+
+ /* Get max. length of long options. */
+ for (i=indent=0; opts[i].short_opt; i++ )
+ {
+ if ( opts[i].long_opt )
+ if ( !opts[i].description || *opts[i].description != '@' )
+ if ( (j=long_opt_strlen(opts+i)) > indent && j < 35 )
+ indent = j;
+ }
+
+ /* Example: " -v, --verbose Viele Sachen ausgeben" */
+ indent += 10;
+ if ( *opts[0].description != '@' )
+ writestrings (0, "Options:", "\n", NULL);
+ for (i=0; opts[i].short_opt; i++ )
+ {
+ s = map_static_macro_string (_( opts[i].description ));
+ if ( s && *s== '@' && !s[1] ) /* Hide this line. */
+ continue;
+ if ( s && *s == '@' ) /* Unindented comment only line. */
+ {
+ for (s++; *s; s++ )
+ {
+ if ( *s == '\n' )
+ {
+ if( s[1] )
+ writestrings (0, "\n", NULL);
+ }
+ else
+ {
+ tmp[0] = *s;
+ tmp[1] = 0;
+ writestrings (0, tmp, NULL);
+ }
+ }
+ writestrings (0, "\n", NULL);
+ continue;
+ }
+
+ j = 3;
+ if ( opts[i].short_opt < 256 )
+ {
+ tmp[0] = opts[i].short_opt;
+ tmp[1] = 0;
+ writestrings (0, " -", tmp, NULL );
+ if ( !opts[i].long_opt )
+ {
+ if (s && *s == '|' )
+ {
+ writestrings (0, " ", NULL); j++;
+ for (s++ ; *s && *s != '|'; s++, j++ )
+ {
+ tmp[0] = *s;
+ tmp[1] = 0;
+ writestrings (0, tmp, NULL);
+ }
+ if ( *s )
+ s++;
+ }
+ }
+ }
+ else
+ writestrings (0, " ", NULL);
+ if ( opts[i].long_opt )
+ {
+ tmp[0] = opts[i].short_opt < 256?',':' ';
+ tmp[1] = 0;
+ j += writestrings (0, tmp, " --", opts[i].long_opt, NULL);
+ if (s && *s == '|' )
+ {
+ if ( *++s != '=' )
+ {
+ writestrings (0, " ", NULL);
+ j++;
+ }
+ for ( ; *s && *s != '|'; s++, j++ )
+ {
+ tmp[0] = *s;
+ tmp[1] = 0;
+ writestrings (0, tmp, NULL);
+ }
+ if ( *s )
+ s++;
+ }
+ writestrings (0, " ", NULL);
+ j += 3;
+ }
+ for (;j < indent; j++ )
+ writestrings (0, " ", NULL);
+ if ( s )
+ {
+ if ( *s && j > indent )
+ {
+ writestrings (0, "\n", NULL);
+ for (j=0;j < indent; j++ )
+ writestrings (0, " ", NULL);
+ }
+ for (; *s; s++ )
+ {
+ if ( *s == '\n' )
+ {
+ if ( s[1] )
+ {
+ writestrings (0, "\n", NULL);
+ for (j=0; j < indent; j++ )
+ writestrings (0, " ", NULL);
+ }
+ }
+ else
+ {
+ tmp[0] = *s;
+ tmp[1] = 0;
+ writestrings (0, tmp, NULL);
+ }
+ }
+ }
+ writestrings (0, "\n", NULL);
+ }
+ if ( (flags & ARGPARSE_FLAG_ONEDASH) )
+ writestrings (0, "\n(A single dash may be used "
+ "instead of the double ones)\n", NULL);
+ }
+ if ( (s=strusage(19)) )
+ {
+ writestrings (0, "\n", NULL);
+ writestrings (0, s, NULL);
+ }
+ flushstrings (0);
+ exit(0);
+}
+
+static void
+show_version ()
+{
+ const char *s;
+ int i;
+
+ /* Version line. */
+ writestrings (0, strusage (11), NULL);
+ if ((s=strusage (12)))
+ writestrings (0, " (", s, ")", NULL);
+ writestrings (0, " ", strusage (13), "\n", NULL);
+ /* Additional version lines. */
+ for (i=20; i < 30; i++)
+ if ((s=strusage (i)))
+ writestrings (0, s, "\n", NULL);
+ /* Copyright string. */
+ if ((s=strusage (14)))
+ writestrings (0, s, "\n", NULL);
+ /* Licence string. */
+ if( (s=strusage (10)) )
+ writestrings (0, s, "\n", NULL);
+ /* Copying conditions. */
+ if ( (s=strusage(15)) )
+ writestrings (0, s, NULL);
+ /* Thanks. */
+ if ((s=strusage(18)))
+ writestrings (0, s, NULL);
+ /* Additional program info. */
+ for (i=30; i < 40; i++ )
+ if ( (s=strusage (i)) )
+ writestrings (0, s, NULL);
+ flushstrings (0);
+}
+
+
+void
+usage (int level)
+{
+ const char *p;
+
+ if (!level)
+ {
+ writestrings (1, strusage(11), " ", strusage(13), "; ",
+ strusage (14), "\n", NULL);
+ flushstrings (1);
+ }
+ else if (level == 1)
+ {
+ p = strusage (40);
+ writestrings (1, p, NULL);
+ if (*p && p[strlen(p)] != '\n')
+ writestrings (1, "\n", NULL);
+ exit (2);
+ }
+ else if (level == 2)
+ {
+ p = strusage (42);
+ if (p && *p == '1')
+ {
+ p = strusage (40);
+ writestrings (1, p, NULL);
+ if (*p && p[strlen(p)] != '\n')
+ writestrings (1, "\n", NULL);
+ }
+ writestrings (0, strusage(41), "\n", NULL);
+ exit (0);
+ }
+}
+
+/* Level
+ * 0: Print copyright string to stderr
+ * 1: Print a short usage hint to stderr and terminate
+ * 2: Print a long usage hint to stdout and terminate
+ * 10: Return license info string
+ * 11: Return the name of the program
+ * 12: Return optional name of package which includes this program.
+ * 13: version string
+ * 14: copyright string
+ * 15: Short copying conditions (with LFs)
+ * 16: Long copying conditions (with LFs)
+ * 17: Optional printable OS name
+ * 18: Optional thanks list (with LFs)
+ * 19: Bug report info
+ *20..29: Additional lib version strings.
+ *30..39: Additional program info (with LFs)
+ * 40: short usage note (with LF)
+ * 41: long usage note (with LF)
+ * 42: Flag string:
+ * First char is '1':
+ * The short usage notes needs to be printed
+ * before the long usage note.
+ */
+const char *
+strusage( int level )
+{
+ const char *p = strusage_handler? strusage_handler(level) : NULL;
+
+ if ( p )
+ return map_static_macro_string (p);
+
+ switch ( level )
+ {
+
+ case 10:
+#if ARGPARSE_GPL_VERSION == 3
+ p = ("License GPLv3+: GNU GPL version 3 or later "
+ "<https://www.gnu.org/licenses/gpl.html>");
+#else
+ p = ("License GPLv2+: GNU GPL version 2 or later "
+ "<https://www.gnu.org/licenses/>");
+#endif
+ break;
+ case 11: p = "foo"; break;
+ case 13: p = "0.0"; break;
+ case 14: p = ARGPARSE_CRIGHT_STR; break;
+ case 15: p =
+"This is free software: you are free to change and redistribute it.\n"
+"There is NO WARRANTY, to the extent permitted by law.\n";
+ break;
+ case 16: p =
+"This is free software; you can redistribute it and/or modify\n"
+"it under the terms of the GNU General Public License as published by\n"
+"the Free Software Foundation; either version "
+ARGPARSE_STR2(ARGPARSE_GPL_VERSION)
+" of the License, or\n"
+"(at your option) any later version.\n\n"
+"It is distributed in the hope that it will be useful,\n"
+"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
+"GNU General Public License for more details.\n\n"
+"You should have received a copy of the GNU General Public License\n"
+"along with this software. If not, see <https://www.gnu.org/licenses/>.\n";
+ break;
+ case 40: /* short and long usage */
+ case 41: p = ""; break;
+ }
+
+ return p;
+}
+
+
+/* Set the usage handler. This function is basically a constructor. */
+void
+set_strusage ( const char *(*f)( int ) )
+{
+ strusage_handler = f;
+}
+
+
+#ifdef TEST
+static struct {
+ int verbose;
+ int debug;
+ char *outfile;
+ char *crf;
+ int myopt;
+ int echo;
+ int a_long_one;
+} opt;
+
+int
+main(int argc, char **argv)
+{
+ ARGPARSE_OPTS opts[] = {
+ ARGPARSE_x('v', "verbose", NONE, 0, "Laut sein"),
+ ARGPARSE_s_n('e', "echo" , ("Zeile ausgeben, damit wir sehen, "
+ "was wir eingegeben haben")),
+ ARGPARSE_s_n('d', "debug", "Debug\nfalls mal etwas\nschief geht"),
+ ARGPARSE_s_s('o', "output", 0 ),
+ ARGPARSE_o_s('c', "cross-ref", "cross-reference erzeugen\n" ),
+ /* Note that on a non-utf8 terminal the ß might garble the output. */
+ ARGPARSE_s_n('s', "street","|Straße|set the name of the street to Straße"),
+ ARGPARSE_o_i('m', "my-option", 0),
+ ARGPARSE_s_n(500, "a-long-option", 0 ),
+ ARGPARSE_end()
+ };
+ ARGPARSE_ARGS pargs = { &argc, &argv, (ARGPARSE_FLAG_ALL
+ | ARGPARSE_FLAG_MIXED
+ | ARGPARSE_FLAG_ONEDASH) };
+ int i;
+
+ while (arg_parse (&pargs, opts))
+ {
+ switch (pargs.r_opt)
+ {
+ case ARGPARSE_IS_ARG :
+ printf ("arg='%s'\n", pargs.r.ret_str);
+ break;
+ case 'v': opt.verbose++; break;
+ case 'e': opt.echo++; break;
+ case 'd': opt.debug++; break;
+ case 'o': opt.outfile = pargs.r.ret_str; break;
+ case 'c': opt.crf = pargs.r_type? pargs.r.ret_str:"a.crf"; break;
+ case 'm': opt.myopt = pargs.r_type? pargs.r.ret_int : 1; break;
+ case 500: opt.a_long_one++; break;
+ default : pargs.err = ARGPARSE_PRINT_WARNING; break;
+ }
+ }
+ for (i=0; i < argc; i++ )
+ printf ("%3d -> (%s)\n", i, argv[i] );
+ puts ("Options:");
+ if (opt.verbose)
+ printf (" verbose=%d\n", opt.verbose );
+ if (opt.debug)
+ printf (" debug=%d\n", opt.debug );
+ if (opt.outfile)
+ printf (" outfile='%s'\n", opt.outfile );
+ if (opt.crf)
+ printf (" crffile='%s'\n", opt.crf );
+ if (opt.myopt)
+ printf (" myopt=%d\n", opt.myopt );
+ if (opt.a_long_one)
+ printf (" a-long-one=%d\n", opt.a_long_one );
+ if (opt.echo)
+ printf (" echo=%d\n", opt.echo );
+
+ return 0;
+}
+#endif /*TEST*/
+
+/**** bottom of file ****/
diff --git a/debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/argparse.h b/debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/argparse.h
new file mode 100644
index 00000000..5b652eba
--- /dev/null
+++ b/debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/argparse.h
@@ -0,0 +1,204 @@
+/* argparse.h - Argument parser for option handling.
+ * Copyright (C) 1998,1999,2000,2001,2006 Free Software Foundation, Inc.
+ *
+ * This file is part of JNLIB, which is a subsystem of GnuPG.
+ *
+ * JNLIB is free software; you can redistribute it and/or modify it
+ * under the terms of either
+ *
+ * - the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * or
+ *
+ * - 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.
+ *
+ * or both in parallel, as here.
+ *
+ * JNLIB 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 copies of the GNU General Public License
+ * and the GNU Lesser General Public License along with this program;
+ * if not, see <https://www.gnu.org/licenses/>.
+ * SPDX-License-Identifier: (GPL-2.0+ OR LGPL-3.0+)
+ */
+
+#ifndef LIBJNLIB_ARGPARSE_H
+#define LIBJNLIB_ARGPARSE_H
+
+#include <stdio.h>
+
+typedef struct
+{
+ int *argc; /* Pointer to ARGC (value subject to change). */
+ char ***argv; /* Pointer to ARGV (value subject to change). */
+ unsigned int flags; /* Global flags. May be set prior to calling the
+ parser. The parser may change the value. */
+ int err; /* Print error description for last option.
+ Either 0, ARGPARSE_PRINT_WARNING or
+ ARGPARSE_PRINT_ERROR. */
+
+ int r_opt; /* Returns option code. */
+ int r_type; /* Returns type of option value. */
+ union {
+ int ret_int;
+ long ret_long;
+ unsigned long ret_ulong;
+ char *ret_str;
+ } r; /* Return values */
+
+ struct {
+ int idx;
+ int inarg;
+ int stopped;
+ const char *last;
+ void *aliases;
+ const void *cur_alias;
+ void *iio_list;
+ } internal; /* Private - do not change. */
+} ARGPARSE_ARGS;
+
+typedef struct
+{
+ int short_opt;
+ const char *long_opt;
+ unsigned int flags;
+ const char *description; /* Optional option description. */
+} ARGPARSE_OPTS;
+
+
+/* Global flags (ARGPARSE_ARGS). */
+#define ARGPARSE_FLAG_KEEP 1 /* Do not remove options form argv. */
+#define ARGPARSE_FLAG_ALL 2 /* Do not stop at last option but return
+ remaining args with R_OPT set to -1. */
+#define ARGPARSE_FLAG_MIXED 4 /* Assume options and args are mixed. */
+#define ARGPARSE_FLAG_NOSTOP 8 /* Do not stop processing at "--". */
+#define ARGPARSE_FLAG_ARG0 16 /* Do not skip the first arg. */
+#define ARGPARSE_FLAG_ONEDASH 32 /* Allow long options with one dash. */
+#define ARGPARSE_FLAG_NOVERSION 64 /* No output for "--version". */
+
+#define ARGPARSE_FLAG_STOP_SEEN 256 /* Set to true if a "--" has been seen. */
+
+/* Flags for each option (ARGPARSE_OPTS). The type code may be
+ ORed with the OPT flags. */
+#define ARGPARSE_TYPE_NONE 0 /* Does not take an argument. */
+#define ARGPARSE_TYPE_INT 1 /* Takes an int argument. */
+#define ARGPARSE_TYPE_STRING 2 /* Takes a string argument. */
+#define ARGPARSE_TYPE_LONG 3 /* Takes a long argument. */
+#define ARGPARSE_TYPE_ULONG 4 /* Takes an unsigned long argument. */
+#define ARGPARSE_OPT_OPTIONAL (1<<3) /* Argument is optional. */
+#define ARGPARSE_OPT_PREFIX (1<<4) /* Allow 0x etc. prefixed values. */
+#define ARGPARSE_OPT_IGNORE (1<<6) /* Ignore command or option. */
+#define ARGPARSE_OPT_COMMAND (1<<7) /* The argument is a command. */
+
+#define ARGPARSE_TYPE_MASK 7 /* Mask for the type values (internal). */
+
+/* A set of macros to make option definitions easier to read. */
+#define ARGPARSE_x(s,l,t,f,d) \
+ { (s), (l), ARGPARSE_TYPE_ ## t | (f), (d) }
+
+#define ARGPARSE_s(s,l,t,d) \
+ { (s), (l), ARGPARSE_TYPE_ ## t, (d) }
+#define ARGPARSE_s_n(s,l,d) \
+ { (s), (l), ARGPARSE_TYPE_NONE, (d) }
+#define ARGPARSE_s_i(s,l,d) \
+ { (s), (l), ARGPARSE_TYPE_INT, (d) }
+#define ARGPARSE_s_s(s,l,d) \
+ { (s), (l), ARGPARSE_TYPE_STRING, (d) }
+#define ARGPARSE_s_l(s,l,d) \
+ { (s), (l), ARGPARSE_TYPE_LONG, (d) }
+#define ARGPARSE_s_u(s,l,d) \
+ { (s), (l), ARGPARSE_TYPE_ULONG, (d) }
+
+#define ARGPARSE_o(s,l,t,d) \
+ { (s), (l), (ARGPARSE_TYPE_ ## t | ARGPARSE_OPT_OPTIONAL), (d) }
+#define ARGPARSE_o_n(s,l,d) \
+ { (s), (l), (ARGPARSE_TYPE_NONE | ARGPARSE_OPT_OPTIONAL), (d) }
+#define ARGPARSE_o_i(s,l,d) \
+ { (s), (l), (ARGPARSE_TYPE_INT | ARGPARSE_OPT_OPTIONAL), (d) }
+#define ARGPARSE_o_s(s,l,d) \
+ { (s), (l), (ARGPARSE_TYPE_STRING | ARGPARSE_OPT_OPTIONAL), (d) }
+#define ARGPARSE_o_l(s,l,d) \
+ { (s), (l), (ARGPARSE_TYPE_LONG | ARGPARSE_OPT_OPTIONAL), (d) }
+#define ARGPARSE_o_u(s,l,d) \
+ { (s), (l), (ARGPARSE_TYPE_ULONG | ARGPARSE_OPT_OPTIONAL), (d) }
+
+#define ARGPARSE_p(s,l,t,d) \
+ { (s), (l), (ARGPARSE_TYPE_ ## t | ARGPARSE_OPT_PREFIX), (d) }
+#define ARGPARSE_p_n(s,l,d) \
+ { (s), (l), (ARGPARSE_TYPE_NONE | ARGPARSE_OPT_PREFIX), (d) }
+#define ARGPARSE_p_i(s,l,d) \
+ { (s), (l), (ARGPARSE_TYPE_INT | ARGPARSE_OPT_PREFIX), (d) }
+#define ARGPARSE_p_s(s,l,d) \
+ { (s), (l), (ARGPARSE_TYPE_STRING | ARGPARSE_OPT_PREFIX), (d) }
+#define ARGPARSE_p_l(s,l,d) \
+ { (s), (l), (ARGPARSE_TYPE_LONG | ARGPARSE_OPT_PREFIX), (d) }
+#define ARGPARSE_p_u(s,l,d) \
+ { (s), (l), (ARGPARSE_TYPE_ULONG | ARGPARSE_OPT_PREFIX), (d) }
+
+#define ARGPARSE_op(s,l,t,d) \
+ { (s), (l), (ARGPARSE_TYPE_ ## t \
+ | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) }
+#define ARGPARSE_op_n(s,l,d) \
+ { (s), (l), (ARGPARSE_TYPE_NONE \
+ | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) }
+#define ARGPARSE_op_i(s,l,d) \
+ { (s), (l), (ARGPARSE_TYPE_INT \
+ | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) }
+#define ARGPARSE_op_s(s,l,d) \
+ { (s), (l), (ARGPARSE_TYPE_STRING \
+ | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) }
+#define ARGPARSE_op_l(s,l,d) \
+ { (s), (l), (ARGPARSE_TYPE_LONG \
+ | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) }
+#define ARGPARSE_op_u(s,l,d) \
+ { (s), (l), (ARGPARSE_TYPE_ULONG \
+ | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) }
+
+#define ARGPARSE_c(s,l,d) \
+ { (s), (l), (ARGPARSE_TYPE_NONE | ARGPARSE_OPT_COMMAND), (d) }
+
+#define ARGPARSE_ignore(s,l) \
+ { (s), (l), (ARGPARSE_OPT_IGNORE), "@" }
+
+#define ARGPARSE_group(s,d) \
+ { (s), NULL, 0, (d) }
+
+#define ARGPARSE_end() { 0, NULL, 0, NULL }
+
+
+/* Other constants. */
+#define ARGPARSE_PRINT_WARNING 1
+#define ARGPARSE_PRINT_ERROR 2
+
+
+/* Error values. */
+#define ARGPARSE_IS_ARG (-1)
+#define ARGPARSE_INVALID_OPTION (-2)
+#define ARGPARSE_MISSING_ARG (-3)
+#define ARGPARSE_KEYWORD_TOO_LONG (-4)
+#define ARGPARSE_READ_ERROR (-5)
+#define ARGPARSE_UNEXPECTED_ARG (-6)
+#define ARGPARSE_INVALID_COMMAND (-7)
+#define ARGPARSE_AMBIGUOUS_OPTION (-8)
+#define ARGPARSE_AMBIGUOUS_COMMAND (-9)
+#define ARGPARSE_INVALID_ALIAS (-10)
+#define ARGPARSE_OUT_OF_CORE (-11)
+#define ARGPARSE_INVALID_ARG (-12)
+
+
+int arg_parse (ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts);
+int optfile_parse (FILE *fp, const char *filename, unsigned *lineno,
+ ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts);
+void usage (int level);
+const char *strusage (int level);
+void set_strusage (const char *(*f)( int ));
+void argparse_register_outfnc (int (*fnc)(int, const char *));
+
+#endif /*LIBJNLIB_ARGPARSE_H*/
diff --git a/debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/password-cache.c b/debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/password-cache.c
new file mode 100644
index 00000000..f9523b1c
--- /dev/null
+++ b/debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/password-cache.c
@@ -0,0 +1,172 @@
+/* password-cache.c - Password cache support.
+ Copyright (C) 2015 g10 Code GmbH
+
+ This file is part of PINENTRY.
+
+ PINENTRY 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.
+
+ PINENTRY 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/>.
+ SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef HAVE_LIBSECRET
+# include <libsecret/secret.h>
+#endif
+
+#include "password-cache.h"
+#include "memory.h"
+
+#ifdef HAVE_LIBSECRET
+static const SecretSchema *
+gpg_schema (void)
+{
+ static const SecretSchema the_schema = {
+ "org.gnupg.Passphrase", SECRET_SCHEMA_NONE,
+ {
+ { "stored-by", SECRET_SCHEMA_ATTRIBUTE_STRING },
+ { "keygrip", SECRET_SCHEMA_ATTRIBUTE_STRING },
+ { "NULL", 0 },
+ }
+ };
+ return &the_schema;
+}
+
+static char *
+keygrip_to_label (const char *keygrip)
+{
+ char const prefix[] = "GnuPG: ";
+ char *label;
+
+ label = malloc (sizeof (prefix) + strlen (keygrip));
+ if (label)
+ {
+ memcpy (label, prefix, sizeof (prefix) - 1);
+ strcpy (&label[sizeof (prefix) - 1], keygrip);
+ }
+ return label;
+}
+#endif
+
+void
+password_cache_save (const char *keygrip, const char *password)
+{
+#ifdef HAVE_LIBSECRET
+ char *label;
+ GError *error = NULL;
+
+ if (! *keygrip)
+ return;
+
+ label = keygrip_to_label (keygrip);
+ if (! label)
+ return;
+
+ if (! secret_password_store_sync (gpg_schema (),
+ SECRET_COLLECTION_DEFAULT,
+ label, password, NULL, &error,
+ "stored-by", "GnuPG Pinentry",
+ "keygrip", keygrip, NULL))
+ {
+ fprintf (stderr, "Failed to cache password for key %s with secret service: %s\n",
+ keygrip, error->message);
+
+ g_error_free (error);
+ }
+
+ free (label);
+#else
+ (void) keygrip;
+ (void) password;
+ return;
+#endif
+}
+
+char *
+password_cache_lookup (const char *keygrip, int *fatal_error)
+{
+#ifdef HAVE_LIBSECRET
+ GError *error = NULL;
+ char *password;
+ char *password2;
+
+ if (! *keygrip)
+ return NULL;
+
+ password = secret_password_lookup_nonpageable_sync
+ (gpg_schema (), NULL, &error,
+ "keygrip", keygrip, NULL);
+
+ if (error != NULL)
+ {
+ if (fatal_error)
+ *fatal_error = 1;
+
+ fprintf (stderr, "Failed to lookup password for key %s with secret service: %s\n",
+ keygrip, error->message);
+ g_error_free (error);
+ return NULL;
+ }
+ if (! password)
+ /* The password for this key is not cached. Just return NULL. */
+ return NULL;
+
+ /* The password needs to be returned in secmem allocated memory. */
+ password2 = secmem_malloc (strlen (password) + 1);
+ if (password2)
+ strcpy(password2, password);
+ else
+ fprintf (stderr, "secmem_malloc failed: can't copy password!\n");
+
+ secret_password_free (password);
+
+ return password2;
+#else
+ (void) keygrip;
+ (void) fatal_error;
+ return NULL;
+#endif
+}
+
+/* Try and remove the cached password for key grip. Returns -1 on
+ error, 0 if the key is not found and 1 if the password was
+ removed. */
+int
+password_cache_clear (const char *keygrip)
+{
+#ifdef HAVE_LIBSECRET
+ GError *error = NULL;
+ int removed = secret_password_clear_sync (gpg_schema (), NULL, &error,
+ "keygrip", keygrip, NULL);
+ if (error != NULL)
+ {
+ fprintf (stderr, "Failed to clear password for key %s with secret service: %s\n",
+ keygrip, error->message);
+ g_debug("%s", error->message);
+ g_error_free (error);
+ return -1;
+ }
+ if (removed)
+ return 1;
+ return 0;
+#else
+ (void) keygrip;
+ return -1;
+#endif
+}
diff --git a/debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/password-cache.h b/debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/password-cache.h
new file mode 100644
index 00000000..d7ccfeef
--- /dev/null
+++ b/debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/password-cache.h
@@ -0,0 +1,30 @@
+/* password-cache.h - Password cache support interfaces.
+ Copyright (C) 2015 g10 Code GmbH
+
+ This file is part of PINENTRY.
+
+ PINENTRY 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.
+
+ PINENTRY 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/>.
+ SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef PASSWORD_CACHE_H
+#define PASSWORD_CACHE_H
+
+void password_cache_save (const char *key_grip, const char *password);
+
+char *password_cache_lookup (const char *key_grip, int *fatal_error);
+
+int password_cache_clear (const char *keygrip);
+
+#endif
diff --git a/debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/pinentry-curses.c b/debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/pinentry-curses.c
new file mode 100644
index 00000000..cc4cecbe
--- /dev/null
+++ b/debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/pinentry-curses.c
@@ -0,0 +1,1410 @@
+/* pinentry-curses.c - A secure curses dialog for PIN entry, library version
+ * Copyright (C) 2002, 2015 g10 Code GmbH
+ *
+ * This file is part of PINENTRY.
+ *
+ * PINENTRY 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.
+ *
+ * PINENTRY 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 <http://www.gnu.org/licenses/>.
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <assert.h>
+#include <curses.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <locale.h>
+#include <iconv.h>
+#if defined(HAVE_LANGINFO_H)
+# include <langinfo.h>
+#elif defined(HAVE_W32_SYSTEM)
+# include <stdio.h>
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+# endif
+# include <windows.h>
+/* A simple replacement for nl_langinfo that only understands
+ CODESET. */
+# define CODESET 1
+char *
+nl_langinfo (int ignore)
+{
+ static char codepage[20];
+ UINT cp = GetACP ();
+
+ (void)ignore;
+
+ sprintf (codepage, "CP%u", cp);
+ return codepage;
+}
+#endif
+#include <limits.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef HAVE_UTIME_H
+#include <utime.h>
+#endif /*HAVE_UTIME_H*/
+
+#include <memory.h>
+
+#ifdef HAVE_WCHAR_H
+#include <wchar.h>
+#endif /*HAVE_WCHAR_H*/
+
+#include <assuan.h>
+
+#include "pinentry.h"
+
+#if GPG_ERROR_VERSION_NUMBER < 0x011900 /* 1.25 */
+# define GPG_ERR_WINDOW_TOO_SMALL 301
+# define GPG_ERR_MISSING_ENVVAR 303
+#endif
+
+
+/* FIXME: We should allow configuration of these button labels and in
+ any case use the default_ok, default_cancel values if available.
+ However, I have no clue about curses and localization. */
+#define STRING_OK "<OK>"
+#define STRING_NOTOK "<No>"
+#define STRING_CANCEL "<Cancel>"
+
+#define USE_COLORS (has_colors () && COLOR_PAIRS >= 2)
+static short pinentry_color[] = { -1, -1, COLOR_BLACK, COLOR_RED,
+ COLOR_GREEN, COLOR_YELLOW, COLOR_BLUE,
+ COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE };
+static int init_screen;
+#ifndef HAVE_DOSISH_SYSTEM
+static int timed_out;
+#endif
+
+typedef enum
+ {
+ DIALOG_POS_NONE,
+ DIALOG_POS_PIN,
+ DIALOG_POS_OK,
+ DIALOG_POS_NOTOK,
+ DIALOG_POS_CANCEL
+ }
+dialog_pos_t;
+
+struct dialog
+{
+ dialog_pos_t pos;
+ int pin_y;
+ int pin_x;
+ /* Width of the PIN field. */
+ int pin_size;
+ /* Cursor location in PIN field. */
+ int pin_loc;
+ int pin_max;
+ /* Length of PIN. */
+ int pin_len;
+ int got_input;
+ int no_echo;
+
+ int ok_y;
+ int ok_x;
+ char *ok;
+ int cancel_y;
+ int cancel_x;
+ char *cancel;
+ int notok_y;
+ int notok_x;
+ char *notok;
+
+ pinentry_t pinentry;
+};
+typedef struct dialog *dialog_t;
+
+/* Flag to remember whether a warning has been printed. */
+static int lc_ctype_unknown_warning;
+
+static char *
+pinentry_utf8_to_local (const char *lc_ctype, const char *text)
+{
+ iconv_t cd;
+ const char *input = text;
+ size_t input_len = strlen (text) + 1;
+ char *output;
+ size_t output_len;
+ char *output_buf;
+ size_t processed;
+ char *old_ctype;
+ char *target_encoding;
+ const char *pgmname = pinentry_get_pgmname ();
+
+ /* If no locale setting could be determined, simply copy the
+ string. */
+ if (!lc_ctype)
+ {
+ if (! lc_ctype_unknown_warning)
+ {
+ fprintf (stderr, "%s: no LC_CTYPE known - assuming UTF-8\n",
+ pgmname);
+ lc_ctype_unknown_warning = 1;
+ }
+ return strdup (text);
+ }
+
+ old_ctype = strdup (setlocale (LC_CTYPE, NULL));
+ if (!old_ctype)
+ return NULL;
+ setlocale (LC_CTYPE, lc_ctype);
+ target_encoding = nl_langinfo (CODESET);
+ if (!target_encoding)
+ target_encoding = "?";
+ setlocale (LC_CTYPE, old_ctype);
+ free (old_ctype);
+
+ /* This is overkill, but simplifies the iconv invocation greatly. */
+ output_len = input_len * MB_LEN_MAX;
+ output_buf = output = malloc (output_len);
+ if (!output)
+ return NULL;
+
+ cd = iconv_open (target_encoding, "UTF-8");
+ if (cd == (iconv_t) -1)
+ {
+ fprintf (stderr, "%s: can't convert from UTF-8 to %s: %s\n",
+ pgmname, target_encoding, strerror (errno));
+ free (output_buf);
+ return NULL;
+ }
+ processed = iconv (cd, (ICONV_CONST char **)&input, &input_len,
+ &output, &output_len);
+ iconv_close (cd);
+ if (processed == (size_t) -1 || input_len)
+ {
+ fprintf (stderr, "%s: error converting from UTF-8 to %s: %s\n",
+ pgmname, target_encoding, strerror (errno));
+ free (output_buf);
+ return NULL;
+ }
+ return output_buf;
+}
+
+/* Convert TEXT which is encoded according to LC_CTYPE to UTF-8. With
+ SECURE set to true, use secure memory for the returned buffer.
+ Return NULL on error. */
+static char *
+pinentry_local_to_utf8 (char *lc_ctype, char *text, int secure)
+{
+ char *old_ctype;
+ char *source_encoding;
+ iconv_t cd;
+ const char *input = text;
+ size_t input_len = strlen (text) + 1;
+ char *output;
+ size_t output_len;
+ char *output_buf;
+ size_t processed;
+ const char *pgmname = pinentry_get_pgmname ();
+
+ /* If no locale setting could be determined, simply copy the
+ string. */
+ if (!lc_ctype)
+ {
+ if (! lc_ctype_unknown_warning)
+ {
+ fprintf (stderr, "%s: no LC_CTYPE known - assuming UTF-8\n",
+ pgmname);
+ lc_ctype_unknown_warning = 1;
+ }
+ output_buf = secure? secmem_malloc (input_len) : malloc (input_len);
+ if (output_buf)
+ strcpy (output_buf, input);
+ return output_buf;
+ }
+
+ old_ctype = strdup (setlocale (LC_CTYPE, NULL));
+ if (!old_ctype)
+ return NULL;
+ setlocale (LC_CTYPE, lc_ctype);
+ source_encoding = nl_langinfo (CODESET);
+ setlocale (LC_CTYPE, old_ctype);
+ free (old_ctype);
+
+ /* This is overkill, but simplifies the iconv invocation greatly. */
+ output_len = input_len * MB_LEN_MAX;
+ output_buf = output = secure? secmem_malloc (output_len):malloc (output_len);
+ if (!output)
+ return NULL;
+
+ cd = iconv_open ("UTF-8", source_encoding);
+ if (cd == (iconv_t) -1)
+ {
+ fprintf (stderr, "%s: can't convert from %s to UTF-8: %s\n",
+ pgmname, source_encoding? source_encoding : "?",
+ strerror (errno));
+ if (secure)
+ secmem_free (output_buf);
+ else
+ free (output_buf);
+ return NULL;
+ }
+ processed = iconv (cd, (ICONV_CONST char **)&input, &input_len,
+ &output, &output_len);
+ iconv_close (cd);
+ if (processed == (size_t) -1 || input_len)
+ {
+ fprintf (stderr, "%s: error converting from %s to UTF-8: %s\n",
+ pgmname, source_encoding? source_encoding : "?",
+ strerror (errno));
+ if (secure)
+ secmem_free (output_buf);
+ else
+ free (output_buf);
+ return NULL;
+ }
+ return output_buf;
+}
+
+#ifdef HAVE_NCURSESW
+typedef wchar_t CH;
+#define STRLEN(x) wcslen (x)
+#define STRWIDTH(x) wcswidth (x, wcslen (x))
+#define ADDCH(x) addnwstr (&x, 1);
+#define CHWIDTH(x) wcwidth (x)
+#define NULLCH L'\0'
+#define NLCH L'\n'
+#define SPCH L' '
+#else
+typedef char CH;
+#define STRLEN(x) strlen (x)
+#define STRWIDTH(x) strlen (x)
+#define ADDCH(x) addch ((unsigned char) x)
+#define CHWIDTH(x) 1
+#define NULLCH '\0'
+#define NLCH '\n'
+#define SPCH ' '
+#endif
+
+/* Return the next line up to MAXWIDTH columns wide in START and LEN.
+ Return value is the width needed for the line.
+ The first invocation should have 0 as *LEN. If the line ends with
+ a \n, it is a normal line that will be continued. If it is a '\0'
+ the end of the text is reached after this line. In all other cases
+ there is a forced line break. A full line is returned and will be
+ continued in the next line. */
+static int
+collect_line (int maxwidth, CH **start_p, int *len_p)
+{
+ int last_space = 0;
+ int len = *len_p;
+ int width = 0;
+ CH *end;
+
+ /* Skip to next line. */
+ *start_p += len;
+ /* Skip leading space. */
+ while (**start_p == SPCH)
+ (*start_p)++;
+
+ end = *start_p;
+ len = 0;
+
+ while (width < maxwidth - 1 && *end != NULLCH && *end != NLCH)
+ {
+ if (*end == SPCH)
+ last_space = len;
+ width += CHWIDTH (*end);
+ len++;
+ end++;
+ }
+
+ if (*end != NULLCH && *end != NLCH && last_space != 0)
+ {
+ /* We reached the end of the available space, but still have
+ characters to go in this line. We can break the line into
+ two parts at a space. */
+ len = last_space;
+ (*start_p)[len] = NLCH;
+ }
+ *len_p = len + 1;
+ return width;
+}
+
+#ifdef HAVE_NCURSESW
+static CH *
+utf8_to_local (char *lc_ctype, char *string)
+{
+ mbstate_t ps;
+ size_t len;
+ char *local;
+ const char *p;
+ wchar_t *wcs = NULL;
+ char *old_ctype = NULL;
+
+ local = pinentry_utf8_to_local (lc_ctype, string);
+ if (!local)
+ return NULL;
+
+ old_ctype = strdup (setlocale (LC_CTYPE, NULL));
+ setlocale (LC_CTYPE, lc_ctype? lc_ctype : "");
+
+ p = local;
+ memset (&ps, 0, sizeof(mbstate_t));
+ len = mbsrtowcs (NULL, &p, strlen (string), &ps);
+ if (len == (size_t)-1)
+ {
+ free (local);
+ goto leave;
+ }
+ wcs = calloc (len + 1, sizeof(wchar_t));
+ if (!wcs)
+ {
+ free (local);
+ goto leave;
+ }
+
+ p = local;
+ memset (&ps, 0, sizeof(mbstate_t));
+ mbsrtowcs (wcs, &p, len, &ps);
+
+ free (local);
+
+ leave:
+ if (old_ctype)
+ {
+ setlocale (LC_CTYPE, old_ctype);
+ free (old_ctype);
+ }
+
+ return wcs;
+}
+#else
+static CH *
+utf8_to_local (const char *lc_ctype, const char *string)
+{
+ return pinentry_utf8_to_local (lc_ctype, string);
+}
+#endif
+
+static int
+dialog_create (pinentry_t pinentry, dialog_t dialog)
+{
+ int err = 0;
+ int size_y;
+ int size_x;
+ int y;
+ int x;
+ int ypos;
+ int xpos;
+ int description_x = 0;
+ int error_x = 0;
+ CH *description = NULL;
+ CH *error = NULL;
+ CH *prompt = NULL;
+
+ dialog->pinentry = pinentry;
+
+#define COPY_OUT(what) \
+ do \
+ if (pinentry->what) \
+ { \
+ what = utf8_to_local (pinentry->lc_ctype, pinentry->what); \
+ if (!what) \
+ { \
+ err = 1; \
+ pinentry->specific_err = gpg_error (GPG_ERR_LOCALE_PROBLEM); \
+ pinentry->specific_err_loc = "dialog_create_copy"; \
+ goto out; \
+ } \
+ } \
+ while (0)
+
+ COPY_OUT (description);
+ COPY_OUT (error);
+ COPY_OUT (prompt);
+
+ /* There is no pinentry->default_notok. Map it to
+ pinentry->notok. */
+#define default_notok notok
+#define MAKE_BUTTON(which,default) \
+ do \
+ { \
+ char *new = NULL; \
+ if (pinentry->default_##which || pinentry->which) \
+ { \
+ int len; \
+ char *msg; \
+ int i, j; \
+ \
+ msg = pinentry->which; \
+ if (! msg) \
+ msg = pinentry->default_##which; \
+ len = strlen (msg); \
+ \
+ new = malloc (len + 3); \
+ if (!new) \
+ { \
+ err = 1; \
+ pinentry->specific_err = gpg_error_from_syserror (); \
+ pinentry->specific_err_loc = "dialog_create_mk_button"; \
+ goto out; \
+ } \
+ \
+ new[0] = '<'; \
+ for (i = 0, j = 1; i < len; i ++, j ++) \
+ { \
+ if (msg[i] == '_') \
+ { \
+ i ++; \
+ if (msg[i] == 0) \
+ /* _ at end of string. */ \
+ break; \
+ } \
+ new[j] = msg[i]; \
+ } \
+ \
+ new[j] = '>'; \
+ new[j + 1] = 0; \
+ } \
+ dialog->which = pinentry_utf8_to_local (pinentry->lc_ctype, \
+ new ? new : default); \
+ free (new); \
+ if (!dialog->which) \
+ { \
+ err = 1; \
+ pinentry->specific_err = gpg_error (GPG_ERR_LOCALE_PROBLEM); \
+ pinentry->specific_err_loc = "dialog_create_utf8conv"; \
+ goto out; \
+ } \
+ } \
+ while (0)
+
+ MAKE_BUTTON (ok, STRING_OK);
+ if (!pinentry->one_button)
+ MAKE_BUTTON (cancel, STRING_CANCEL);
+ else
+ dialog->cancel = NULL;
+ if (!pinentry->one_button && pinentry->notok)
+ MAKE_BUTTON (notok, STRING_NOTOK);
+ else
+ dialog->notok = NULL;
+
+ getmaxyx (stdscr, size_y, size_x);
+
+ /* Check if all required lines fit on the screen. */
+ y = 1; /* Top frame. */
+ if (description)
+ {
+ CH *start = description;
+ int len = 0;
+
+ do
+ {
+ int width = collect_line (size_x - 4, &start, &len);
+
+ if (width > description_x)
+ description_x = width;
+ y++;
+ }
+ while (start[len - 1]);
+ y++;
+ }
+
+ if (pinentry->pin)
+ {
+ if (error)
+ {
+ CH *p = error;
+ int err_x = 0;
+
+ while (*p)
+ {
+ if (*(p++) == '\n')
+ {
+ if (err_x > error_x)
+ error_x = err_x;
+ y++;
+ err_x = 0;
+ }
+ else
+ err_x++;
+ }
+ if (err_x > error_x)
+ error_x = err_x;
+ y += 2; /* Error message. */
+ }
+ y += 2; /* Pin entry field. */
+ }
+ y += 2; /* OK/Cancel and bottom frame. */
+
+ if (y > size_y)
+ {
+ err = 1;
+ pinentry->specific_err = gpg_error (size_y < 0? GPG_ERR_MISSING_ENVVAR
+ /* */ : GPG_ERR_WINDOW_TOO_SMALL);
+ pinentry->specific_err_loc = "dialog_create";
+ goto out;
+ }
+
+ /* Check if all required columns fit on the screen. */
+ x = 0;
+ if (description)
+ {
+ int new_x = description_x;
+ if (new_x > size_x - 4)
+ new_x = size_x - 4;
+ if (new_x > x)
+ x = new_x;
+ }
+ if (pinentry->pin)
+ {
+#define MIN_PINENTRY_LENGTH 40
+ int new_x;
+
+ if (error)
+ {
+ new_x = error_x;
+ if (new_x > size_x - 4)
+ new_x = size_x - 4;
+ if (new_x > x)
+ x = new_x;
+ }
+
+ new_x = MIN_PINENTRY_LENGTH;
+ if (prompt)
+ {
+ new_x += STRWIDTH (prompt) + 1; /* One space after prompt. */
+ }
+ if (new_x > size_x - 4)
+ new_x = size_x - 4;
+ if (new_x > x)
+ x = new_x;
+ }
+ /* We position the buttons after the first, second and third fourth
+ of the width. Account for rounding. */
+ if (x < 3 * strlen (dialog->ok))
+ x = 3 * strlen (dialog->ok);
+ if (dialog->cancel)
+ if (x < 3 * strlen (dialog->cancel))
+ x = 3 * strlen (dialog->cancel);
+ if (dialog->notok)
+ if (x < 3 * strlen (dialog->notok))
+ x = 3 * strlen (dialog->notok);
+
+ /* Add the frame. */
+ x += 4;
+
+ if (x > size_x)
+ {
+ err = 1;
+ pinentry->specific_err = gpg_error (size_x < 0? GPG_ERR_MISSING_ENVVAR
+ /* */ : GPG_ERR_WINDOW_TOO_SMALL);
+ pinentry->specific_err_loc = "dialog_create";
+ goto out;
+ }
+
+ dialog->pos = DIALOG_POS_NONE;
+ dialog->pin_max = pinentry->pin_len;
+ dialog->pin_loc = 0;
+ dialog->pin_len = 0;
+ ypos = (size_y - y) / 2;
+ xpos = (size_x - x) / 2;
+ move (ypos, xpos);
+ addch (ACS_ULCORNER);
+ hline (0, x - 2);
+ move (ypos, xpos + x - 1);
+ addch (ACS_URCORNER);
+ move (ypos + 1, xpos + x - 1);
+ vline (0, y - 2);
+ move (ypos + y - 1, xpos);
+ addch (ACS_LLCORNER);
+ hline (0, x - 2);
+ move (ypos + y - 1, xpos + x - 1);
+ addch (ACS_LRCORNER);
+ ypos++;
+ if (description)
+ {
+ CH *start = description;
+ int len = 0;
+
+ do
+ {
+ int i;
+
+ move (ypos, xpos);
+ addch (ACS_VLINE);
+ addch (' ');
+ collect_line (size_x - 4, &start, &len);
+ for (i = 0; i < len - 1; i++)
+ {
+ ADDCH (start[i]);
+ }
+ if (start[len - 1] != NULLCH && start[len - 1] != NLCH)
+ ADDCH (start[len - 1]);
+ ypos++;
+ }
+ while (start[len - 1]);
+ move (ypos, xpos);
+ addch (ACS_VLINE);
+ ypos++;
+ }
+ if (pinentry->pin)
+ {
+ int i;
+
+ if (error)
+ {
+ CH *p = error;
+ i = 0;
+
+ while (*p)
+ {
+ move (ypos, xpos);
+ addch (ACS_VLINE);
+ addch (' ');
+ if (USE_COLORS && pinentry->color_so != PINENTRY_COLOR_NONE)
+ {
+ attroff (COLOR_PAIR (1) | (pinentry->color_fg_bright ? A_BOLD : 0));
+ attron (COLOR_PAIR (2) | (pinentry->color_so_bright ? A_BOLD : 0));
+ }
+ else
+ standout ();
+ for (;*p && *p != NLCH; p++)
+ if (i < x - 4)
+ {
+ i++;
+ ADDCH (*p);
+ }
+ if (USE_COLORS && pinentry->color_so != PINENTRY_COLOR_NONE)
+ {
+ attroff (COLOR_PAIR (2) | (pinentry->color_so_bright ? A_BOLD : 0));
+ attron (COLOR_PAIR (1) | (pinentry->color_fg_bright ? A_BOLD : 0));
+ }
+ else
+ standend ();
+ if (*p == '\n')
+ p++;
+ i = 0;
+ ypos++;
+ }
+ move (ypos, xpos);
+ addch (ACS_VLINE);
+ ypos++;
+ }
+
+ move (ypos, xpos);
+ addch (ACS_VLINE);
+ addch (' ');
+
+ dialog->pin_y = ypos;
+ dialog->pin_x = xpos + 2;
+ dialog->pin_size = x - 4;
+ if (prompt)
+ {
+ CH *p = prompt;
+ i = STRWIDTH (prompt);
+ if (i > x - 4 - MIN_PINENTRY_LENGTH)
+ i = x - 4 - MIN_PINENTRY_LENGTH;
+ dialog->pin_x += i + 1;
+ dialog->pin_size -= i + 1;
+ i = STRLEN (prompt);
+ while (i-- > 0)
+ {
+ ADDCH (*(p++));
+ }
+ addch (' ');
+ }
+ for (i = 0; i < dialog->pin_size; i++)
+ addch ('_');
+ ypos++;
+ move (ypos, xpos);
+ addch (ACS_VLINE);
+ ypos++;
+ }
+ move (ypos, xpos);
+ addch (ACS_VLINE);
+
+ if (dialog->cancel || dialog->notok)
+ {
+ dialog->ok_y = ypos;
+ /* Calculating the left edge of the left button, rounding down. */
+ dialog->ok_x = xpos + 2 + ((x - 4) / 3 - strlen (dialog->ok)) / 2;
+ move (dialog->ok_y, dialog->ok_x);
+ addstr (dialog->ok);
+
+ if (! pinentry->pin && dialog->notok)
+ {
+ dialog->notok_y = ypos;
+ /* Calculating the left edge of the middle button, rounding up. */
+ dialog->notok_x = xpos + x / 2 - strlen (dialog->notok) / 2;
+ move (dialog->notok_y, dialog->notok_x);
+ addstr (dialog->notok);
+ }
+ if (dialog->cancel)
+ {
+ dialog->cancel_y = ypos;
+ /* Calculating the left edge of the right button, rounding up. */
+ dialog->cancel_x = xpos + x - 2 - ((x - 4) / 3 + strlen (dialog->cancel)) / 2;
+ move (dialog->cancel_y, dialog->cancel_x);
+ addstr (dialog->cancel);
+ }
+ }
+ else
+ {
+ dialog->ok_y = ypos;
+ /* Calculating the left edge of the OK button, rounding down. */
+ dialog->ok_x = xpos + x / 2 - strlen (dialog->ok) / 2;
+ move (dialog->ok_y, dialog->ok_x);
+ addstr (dialog->ok);
+ }
+
+ dialog->got_input = 0;
+ dialog->no_echo = 0;
+
+ out:
+ if (description)
+ free (description);
+ if (error)
+ free (error);
+ if (prompt)
+ free (prompt);
+ return err;
+}
+
+
+static void
+set_cursor_state (int on)
+{
+ static int normal_state = -1;
+ static int on_last;
+
+ if (normal_state < 0 && !on)
+ {
+ normal_state = curs_set (0);
+ on_last = on;
+ }
+ else if (on != on_last)
+ {
+ curs_set (on ? normal_state : 0);
+ on_last = on;
+ }
+}
+
+static int
+dialog_switch_pos (dialog_t diag, dialog_pos_t new_pos)
+{
+ if (new_pos != diag->pos)
+ {
+ switch (diag->pos)
+ {
+ case DIALOG_POS_OK:
+ move (diag->ok_y, diag->ok_x);
+ addstr (diag->ok);
+ break;
+ case DIALOG_POS_NOTOK:
+ if (diag->notok)
+ {
+ move (diag->notok_y, diag->notok_x);
+ addstr (diag->notok);
+ }
+ break;
+ case DIALOG_POS_CANCEL:
+ if (diag->cancel)
+ {
+ move (diag->cancel_y, diag->cancel_x);
+ addstr (diag->cancel);
+ }
+ break;
+ default:
+ break;
+ }
+ diag->pos = new_pos;
+ switch (diag->pos)
+ {
+ case DIALOG_POS_PIN:
+ move (diag->pin_y, diag->pin_x + diag->pin_loc);
+ set_cursor_state (1);
+ break;
+ case DIALOG_POS_OK:
+ set_cursor_state (0);
+ move (diag->ok_y, diag->ok_x);
+ standout ();
+ addstr (diag->ok);
+ standend ();
+ move (diag->ok_y, diag->ok_x);
+ break;
+ case DIALOG_POS_NOTOK:
+ if (diag->notok)
+ {
+ set_cursor_state (0);
+ move (diag->notok_y, diag->notok_x);
+ standout ();
+ addstr (diag->notok);
+ standend ();
+ move (diag->notok_y, diag->notok_x);
+ }
+ break;
+ case DIALOG_POS_CANCEL:
+ if (diag->cancel)
+ {
+ set_cursor_state (0);
+ move (diag->cancel_y, diag->cancel_x);
+ standout ();
+ addstr (diag->cancel);
+ standend ();
+ move (diag->cancel_y, diag->cancel_x);
+ }
+ break;
+ case DIALOG_POS_NONE:
+ set_cursor_state (0);
+ break;
+ }
+ refresh ();
+ }
+ return 0;
+}
+
+/* XXX Assume that field width is at least > 5. */
+static void
+dialog_input (dialog_t diag, int alt, int chr)
+{
+ int old_loc = diag->pin_loc;
+ assert (diag->pinentry->pin);
+ assert (diag->pos == DIALOG_POS_PIN);
+
+ if (alt && chr == KEY_BACKSPACE)
+ /* Remap alt-backspace to control-W. */
+ chr = 'w' - 'a' + 1;
+
+ switch (chr)
+ {
+ case KEY_BACKSPACE:
+ /* control-h. */
+ case 'h' - 'a' + 1:
+ /* ASCII DEL. What Mac OS X apparently emits when the "delete"
+ (backspace) key is pressed. */
+ case 127:
+ if (diag->pin_len > 0)
+ {
+ diag->pin_len--;
+ diag->pin_loc--;
+ if (diag->pin_loc == 0 && diag->pin_len > 0)
+ {
+ diag->pin_loc = diag->pin_size - 5;
+ if (diag->pin_loc > diag->pin_len)
+ diag->pin_loc = diag->pin_len;
+ }
+ }
+ else if (!diag->got_input)
+ {
+ diag->no_echo = 1;
+ move (diag->pin_y, diag->pin_x);
+ addstr ("[no echo]");
+ }
+ break;
+
+ case 'l' - 'a' + 1: /* control-l */
+ /* Refresh the screen. */
+ endwin ();
+ refresh ();
+ break;
+
+ case 'u' - 'a' + 1: /* control-u */
+ /* Erase the whole line. */
+ if (diag->pin_len > 0)
+ {
+ diag->pin_len = 0;
+ diag->pin_loc = 0;
+ }
+ break;
+
+ case 'w' - 'a' + 1: /* control-w. */
+ while (diag->pin_len > 0
+ && diag->pinentry->pin[diag->pin_len - 1] == ' ')
+ {
+ diag->pin_len --;
+ diag->pin_loc --;
+ if (diag->pin_loc < 0)
+ {
+ diag->pin_loc += diag->pin_size;
+ if (diag->pin_loc > diag->pin_len)
+ diag->pin_loc = diag->pin_len;
+ }
+ }
+ while (diag->pin_len > 0
+ && diag->pinentry->pin[diag->pin_len - 1] != ' ')
+ {
+ diag->pin_len --;
+ diag->pin_loc --;
+ if (diag->pin_loc < 0)
+ {
+ diag->pin_loc += diag->pin_size;
+ if (diag->pin_loc > diag->pin_len)
+ diag->pin_loc = diag->pin_len;
+ }
+ }
+
+ break;
+
+ default:
+ if (chr > 0 && chr < 256 && diag->pin_len < diag->pin_max)
+ {
+ /* Make sure there is enough room for this character and a
+ following NUL byte. */
+ if (! pinentry_setbufferlen (diag->pinentry, diag->pin_len + 2))
+ {
+ /* Bail. Here we use a simple approach. It would be
+ better to have a pinentry_bug function. */
+ assert (!"setbufferlen failed");
+ abort ();
+ }
+
+ diag->pinentry->pin[diag->pin_len] = (char) chr;
+ diag->pin_len++;
+ diag->pin_loc++;
+ if (diag->pin_loc == diag->pin_size && diag->pin_len < diag->pin_max)
+ {
+ diag->pin_loc = 5;
+ if (diag->pin_loc < diag->pin_size - (diag->pin_max + 1 - diag->pin_len))
+ diag->pin_loc = diag->pin_size - (diag->pin_max + 1 - diag->pin_len);
+ }
+ }
+ break;
+ }
+
+ diag->got_input = 1;
+
+ if (!diag->no_echo)
+ {
+ if (old_loc < diag->pin_loc)
+ {
+ move (diag->pin_y, diag->pin_x + old_loc);
+ while (old_loc++ < diag->pin_loc)
+ addch ('*');
+ }
+ else if (old_loc > diag->pin_loc)
+ {
+ move (diag->pin_y, diag->pin_x + diag->pin_loc);
+ while (old_loc-- > diag->pin_loc)
+ addch ('_');
+ }
+ move (diag->pin_y, diag->pin_x + diag->pin_loc);
+ }
+}
+
+static int
+dialog_run (pinentry_t pinentry, const char *tty_name, const char *tty_type)
+{
+ int confirm_mode = !pinentry->pin;
+ struct dialog diag;
+ FILE *ttyfi = NULL;
+ FILE *ttyfo = NULL;
+ SCREEN *screen = 0;
+ int done = 0;
+ char *pin_utf8;
+ int alt = 0;
+#ifndef HAVE_DOSISH_SYSTEM
+ int no_input = 1;
+#endif
+
+#ifdef HAVE_NCURSESW
+ char *old_ctype = NULL;
+
+ if (pinentry->lc_ctype)
+ {
+ old_ctype = strdup (setlocale (LC_CTYPE, NULL));
+ setlocale (LC_CTYPE, pinentry->lc_ctype);
+ }
+ else
+ setlocale (LC_CTYPE, "");
+#endif
+
+ /* Open the desired terminal if necessary. */
+ if (tty_name)
+ {
+ ttyfi = fopen (tty_name, "r");
+ if (!ttyfi)
+ {
+ pinentry->specific_err = gpg_error_from_syserror ();
+ pinentry->specific_err_loc = "open_tty_for_read";
+#ifdef HAVE_NCURSESW
+ free (old_ctype);
+#endif
+ return confirm_mode? 0 : -1;
+ }
+ ttyfo = fopen (tty_name, "w");
+ if (!ttyfo)
+ {
+ int err = errno;
+ fclose (ttyfi);
+ errno = err;
+ pinentry->specific_err = gpg_error_from_syserror ();
+ pinentry->specific_err_loc = "open_tty_for_write";
+#ifdef HAVE_NCURSESW
+ free (old_ctype);
+#endif
+ return confirm_mode? 0 : -1;
+ }
+ screen = newterm (tty_type, ttyfo, ttyfi);
+ if (!screen)
+ {
+ pinentry->specific_err = gpg_error (GPG_ERR_WINDOW_TOO_SMALL);
+ pinentry->specific_err_loc = "curses_init";
+ fclose (ttyfo);
+ fclose (ttyfi);
+#ifdef HAVE_NCURSESW
+ free (old_ctype);
+#endif
+ return confirm_mode? 0 : -1;
+ }
+ set_term (screen);
+ }
+ else
+ {
+ if (!init_screen)
+ {
+ if (!(isatty(fileno(stdin)) && isatty(fileno(stdout))))
+ {
+ errno = ENOTTY;
+ pinentry->specific_err = gpg_error_from_syserror ();
+ pinentry->specific_err_loc = "isatty";
+#ifdef HAVE_NCURSESW
+ free (old_ctype);
+#endif
+ return confirm_mode? 0 : -1;
+ }
+ init_screen = 1;
+ initscr ();
+ }
+ else
+ clear ();
+ }
+
+ keypad (stdscr, TRUE); /* Enable keyboard mapping. */
+ nonl (); /* Tell curses not to do NL->CR/NL on output. */
+ cbreak (); /* Take input chars one at a time, no wait for \n. */
+ noecho (); /* Don't echo input - in color. */
+
+ if (pinentry->ttyalert)
+ {
+ if (! strcmp(pinentry->ttyalert, "beep"))
+ beep ();
+ else if (! strcmp(pinentry->ttyalert, "flash"))
+ flash ();
+ }
+
+ if (has_colors ())
+ {
+ start_color ();
+
+ /* Ncurses has use_default_colors, an extentions to the curses
+ library, which allows use of -1 to select default color. */
+#ifdef NCURSES_VERSION
+ use_default_colors ();
+#else
+ /* With no extention, we need to specify color explicitly. */
+ if (pinentry->color_fg == PINENTRY_COLOR_DEFAULT)
+ pinentry->color_fg = PINENTRY_COLOR_WHITE;
+ if (pinentry->color_bg == PINENTRY_COLOR_DEFAULT)
+ pinentry->color_bg = PINENTRY_COLOR_BLACK;
+#endif
+
+ if (pinentry->color_so == PINENTRY_COLOR_DEFAULT)
+ {
+ pinentry->color_so = PINENTRY_COLOR_RED;
+ pinentry->color_so_bright = 1;
+ }
+ if (COLOR_PAIRS >= 2)
+ {
+ init_pair (1, pinentry_color[pinentry->color_fg],
+ pinentry_color[pinentry->color_bg]);
+ init_pair (2, pinentry_color[pinentry->color_so],
+ pinentry_color[pinentry->color_bg]);
+
+ bkgd (COLOR_PAIR (1));
+ attron (COLOR_PAIR (1) | (pinentry->color_fg_bright ? A_BOLD : 0));
+ }
+ }
+ refresh ();
+
+ /* Create the dialog. */
+ if (dialog_create (pinentry, &diag))
+ {
+ /* Note: pinentry->specific_err has already been set. */
+ endwin ();
+ if (screen)
+ delscreen (screen);
+
+#ifdef HAVE_NCURSESW
+ if (old_ctype)
+ {
+ setlocale (LC_CTYPE, old_ctype);
+ free (old_ctype);
+ }
+#endif
+ if (ttyfi)
+ fclose (ttyfi);
+ if (ttyfo)
+ fclose (ttyfo);
+ return -2;
+ }
+ dialog_switch_pos (&diag, confirm_mode? DIALOG_POS_OK : DIALOG_POS_PIN);
+
+#ifndef HAVE_DOSISH_SYSTEM
+ wtimeout (stdscr, 70);
+#endif
+
+ do
+ {
+ int c;
+
+ c = wgetch (stdscr); /* Refresh, accept single keystroke of input. */
+#ifndef HAVE_DOSISH_SYSTEM
+ if (timed_out && no_input)
+ {
+ done = -2;
+ pinentry->specific_err = gpg_error (GPG_ERR_TIMEOUT);
+ break;
+ }
+#endif
+
+ switch (c)
+ {
+ case ERR:
+#ifndef HAVE_DOSISH_SYSTEM
+ continue;
+#else
+ done = -2;
+ break;
+#endif
+
+ case 27: /* Alt was pressed. */
+ alt = 1;
+ /* Get the next key press. */
+ continue;
+
+ case KEY_LEFT:
+ case KEY_UP:
+ switch (diag.pos)
+ {
+ case DIALOG_POS_OK:
+ if (!confirm_mode)
+ dialog_switch_pos (&diag, DIALOG_POS_PIN);
+ break;
+ case DIALOG_POS_NOTOK:
+ dialog_switch_pos (&diag, DIALOG_POS_OK);
+ break;
+ case DIALOG_POS_CANCEL:
+ if (diag.notok)
+ dialog_switch_pos (&diag, DIALOG_POS_NOTOK);
+ else
+ dialog_switch_pos (&diag, DIALOG_POS_OK);
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case KEY_RIGHT:
+ case KEY_DOWN:
+ switch (diag.pos)
+ {
+ case DIALOG_POS_PIN:
+ dialog_switch_pos (&diag, DIALOG_POS_OK);
+ break;
+ case DIALOG_POS_OK:
+ if (diag.notok)
+ dialog_switch_pos (&diag, DIALOG_POS_NOTOK);
+ else
+ dialog_switch_pos (&diag, DIALOG_POS_CANCEL);
+ break;
+ case DIALOG_POS_NOTOK:
+ dialog_switch_pos (&diag, DIALOG_POS_CANCEL);
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case '\t':
+ switch (diag.pos)
+ {
+ case DIALOG_POS_PIN:
+ dialog_switch_pos (&diag, DIALOG_POS_OK);
+ break;
+ case DIALOG_POS_OK:
+ if (diag.notok)
+ dialog_switch_pos (&diag, DIALOG_POS_NOTOK);
+ else
+ dialog_switch_pos (&diag, DIALOG_POS_CANCEL);
+ break;
+ case DIALOG_POS_NOTOK:
+ dialog_switch_pos (&diag, DIALOG_POS_CANCEL);
+ break;
+ case DIALOG_POS_CANCEL:
+ if (confirm_mode)
+ dialog_switch_pos (&diag, DIALOG_POS_OK);
+ else
+ dialog_switch_pos (&diag, DIALOG_POS_PIN);
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case '\005':
+ done = -2;
+ break;
+
+ case '\r':
+ switch (diag.pos)
+ {
+ case DIALOG_POS_PIN:
+ case DIALOG_POS_OK:
+ done = 1;
+ break;
+ case DIALOG_POS_NOTOK:
+ done = -1;
+ break;
+ case DIALOG_POS_CANCEL:
+ done = -2;
+ break;
+ case DIALOG_POS_NONE:
+ break;
+ }
+ break;
+
+ default:
+ if (diag.pos == DIALOG_POS_PIN)
+ dialog_input (&diag, alt, c);
+ }
+#ifndef HAVE_DOSISH_SYSTEM
+ no_input = 0;
+#endif
+ if (c != -1)
+ alt = 0;
+ }
+ while (!done);
+
+ if (!confirm_mode)
+ {
+ /* NUL terminate the passphrase. dialog_run makes sure there is
+ enough space for the terminating NUL byte. */
+ diag.pinentry->pin[diag.pin_len] = 0;
+ }
+
+ set_cursor_state (1);
+ endwin ();
+ if (screen)
+ delscreen (screen);
+
+#ifdef HAVE_NCURSESW
+ if (old_ctype)
+ {
+ setlocale (LC_CTYPE, old_ctype);
+ free (old_ctype);
+ }
+#endif
+ if (ttyfi)
+ fclose (ttyfi);
+ if (ttyfo)
+ fclose (ttyfo);
+ /* XXX Factor out into dialog_release or something. */
+ free (diag.ok);
+ if (diag.cancel)
+ free (diag.cancel);
+ if (diag.notok)
+ free (diag.notok);
+
+ if (!confirm_mode)
+ {
+ pinentry->locale_err = 1;
+ pin_utf8 = pinentry_local_to_utf8 (pinentry->lc_ctype, pinentry->pin, 1);
+ if (pin_utf8)
+ {
+ pinentry_setbufferlen (pinentry, strlen (pin_utf8) + 1);
+ if (pinentry->pin)
+ strcpy (pinentry->pin, pin_utf8);
+ secmem_free (pin_utf8);
+ pinentry->locale_err = 0;
+ }
+ }
+
+ if (done == -2)
+ pinentry->canceled = 1;
+
+ /* In confirm mode return cancel instead of error. */
+ if (confirm_mode)
+ return done < 0 ? 0 : 1;
+
+ return done < 0 ? -1 : diag.pin_len;
+}
+
+
+/* If a touch has been registered, touch that file. */
+static void
+do_touch_file (pinentry_t pinentry)
+{
+#ifdef HAVE_UTIME_H
+ struct stat st;
+ time_t tim;
+
+ if (!pinentry->touch_file || !*pinentry->touch_file)
+ return;
+
+ if (stat (pinentry->touch_file, &st))
+ return; /* Oops. */
+
+ /* Make sure that we actually update the mtime. */
+ while ( (tim = time (NULL)) == st.st_mtime )
+ sleep (1);
+
+ /* Update but ignore errors as we can't do anything in that case.
+ Printing error messages may even clubber the display further. */
+ utime (pinentry->touch_file, NULL);
+#endif /*HAVE_UTIME_H*/
+}
+
+#ifndef HAVE_DOSISH_SYSTEM
+static void
+catchsig (int sig)
+{
+ if (sig == SIGALRM)
+ timed_out = 1;
+}
+#endif
+
+int
+curses_cmd_handler (pinentry_t pinentry)
+{
+ int rc;
+
+#ifndef HAVE_DOSISH_SYSTEM
+ timed_out = 0;
+
+ if (pinentry->timeout)
+ {
+ struct sigaction sa;
+
+ memset (&sa, 0, sizeof(sa));
+ sa.sa_handler = catchsig;
+ sigaction (SIGALRM, &sa, NULL);
+ alarm (pinentry->timeout);
+ }
+#endif
+
+ rc = dialog_run (pinentry, pinentry->ttyname, pinentry->ttytype_l);
+ do_touch_file (pinentry);
+ return rc;
+}
diff --git a/debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/pinentry-curses.h b/debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/pinentry-curses.h
new file mode 100644
index 00000000..b33f1349
--- /dev/null
+++ b/debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/pinentry-curses.h
@@ -0,0 +1,35 @@
+/* pinentry-curses.h - A secure curses dialog for PIN entry, library version
+ * Copyright (C) 2002 g10 Code GmbH
+ *
+ * This file is part of PINENTRY.
+ *
+ * PINENTRY 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.
+ *
+ * PINENTRY 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 <http://www.gnu.org/licenses/>.
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+#ifndef PINENTRY_CURSES_H
+#define PINENTRY_CURSES_H
+
+#include "pinentry.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int curses_cmd_handler (pinentry_t pinentry);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PINENTRY_CURSES_H */
diff --git a/debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/pinentry-emacs.c b/debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/pinentry-emacs.c
new file mode 100644
index 00000000..9685b67d
--- /dev/null
+++ b/debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/pinentry-emacs.c
@@ -0,0 +1,721 @@
+/* pinentry-emacs.c - A secure emacs dialog for PIN entry, library version
+ * Copyright (C) 2015 Daiki Ueno
+ *
+ * This file is part of PINENTRY.
+ *
+ * PINENTRY 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.
+ *
+ * PINENTRY 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/>.
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+#include <assert.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#ifdef HAVE_UTIME_H
+#include <utime.h>
+#endif /*HAVE_UTIME_H*/
+
+#include <assuan.h>
+
+#include "pinentry-emacs.h"
+#include "memory.h"
+#include "secmem-util.h"
+
+/* The communication mechanism is similar to emacsclient, but there
+ are a few differences:
+
+ - To avoid unnecessary character escaping and encoding conversion,
+ we use a subset of the Pinentry Assuan protocol, instead of the
+ emacsclient protocol.
+
+ - We only use a Unix domain socket, while emacsclient has an
+ ability to use a TCP socket. The socket file is located at
+ ${TMPDIR-/tmp}/emacs$(id -u)/pinentry (i.e., under the same
+ directory as the socket file used by emacsclient, so the same
+ permission and file owner settings apply).
+
+ - The server implementation can be found in pinentry.el, which is
+ available in Emacs 25+ or from ELPA. */
+
+#define LINELENGTH ASSUAN_LINELENGTH
+#define SEND_BUFFER_SIZE 4096
+#define INITIAL_TIMEOUT 60
+
+static int initial_timeout = INITIAL_TIMEOUT;
+
+#undef MIN
+#define MIN(x, y) ((x) < (y) ? (x) : (y))
+
+#undef MAX
+#define MAX(x, y) ((x) < (y) ? (y) : (x))
+
+#ifndef SUN_LEN
+# define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) \
+ + strlen ((ptr)->sun_path))
+#endif
+
+/* FIXME: We could use the I/O functions in Assuan directly, once
+ Pinentry links to libassuan. */
+static int emacs_socket = -1;
+static char send_buffer[SEND_BUFFER_SIZE + 1];
+static int send_buffer_length; /* Fill pointer for the send buffer. */
+
+static pinentry_cmd_handler_t fallback_cmd_handler;
+
+#ifndef HAVE_DOSISH_SYSTEM
+static int timed_out;
+#endif
+
+static int
+set_socket (const char *socket_name)
+{
+ struct sockaddr_un unaddr;
+ struct stat statbuf;
+ const char *tmpdir;
+ char *tmpdir_storage = NULL;
+ char *socket_name_storage = NULL;
+ uid_t uid;
+
+ unaddr.sun_family = AF_UNIX;
+
+ /* We assume 32-bit UIDs, which can be represented with 10 decimal
+ digits. */
+ uid = getuid ();
+ if (uid != (uint32_t) uid)
+ {
+ fprintf (stderr, "UID is too large\n");
+ return 0;
+ }
+
+ tmpdir = getenv ("TMPDIR");
+ if (!tmpdir)
+ {
+#ifdef _CS_DARWIN_USER_TEMP_DIR
+ size_t n = confstr (_CS_DARWIN_USER_TEMP_DIR, NULL, (size_t) 0);
+ if (n > 0)
+ {
+ tmpdir = tmpdir_storage = malloc (n);
+ if (!tmpdir)
+ {
+ fprintf (stderr, "out of core\n");
+ return 0;
+ }
+ confstr (_CS_DARWIN_USER_TEMP_DIR, tmpdir_storage, n);
+ }
+ else
+#endif
+ tmpdir = "/tmp";
+ }
+
+ socket_name_storage = malloc (strlen (tmpdir)
+ + strlen ("/emacs") + 10 + strlen ("/")
+ + strlen (socket_name)
+ + 1);
+ if (!socket_name_storage)
+ {
+ fprintf (stderr, "out of core\n");
+ free (tmpdir_storage);
+ return 0;
+ }
+
+ sprintf (socket_name_storage, "%s/emacs%u/%s", tmpdir,
+ (uint32_t) uid, socket_name);
+ free (tmpdir_storage);
+
+ if (strlen (socket_name_storage) >= sizeof (unaddr.sun_path))
+ {
+ fprintf (stderr, "socket name is too long\n");
+ free (socket_name_storage);
+ return 0;
+ }
+
+ strcpy (unaddr.sun_path, socket_name_storage);
+ free (socket_name_storage);
+
+ /* See if the socket exists, and if it's owned by us. */
+ if (stat (unaddr.sun_path, &statbuf) == -1)
+ {
+ perror ("stat");
+ return 0;
+ }
+
+ if (statbuf.st_uid != geteuid ())
+ {
+ fprintf (stderr, "socket is not owned by the same user\n");
+ return 0;
+ }
+
+ emacs_socket = socket (AF_UNIX, SOCK_STREAM, 0);
+ if (emacs_socket < 0)
+ {
+ perror ("socket");
+ return 0;
+ }
+
+ if (connect (emacs_socket, (struct sockaddr *) &unaddr,
+ SUN_LEN (&unaddr)) < 0)
+ {
+ perror ("connect");
+ close (emacs_socket);
+ emacs_socket = -1;
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Percent-escape control characters in DATA. Return a newly
+ allocated string. */
+static char *
+escape (const char *data)
+{
+ char *buffer, *out_p;
+ size_t length, buffer_length;
+ size_t offset;
+ size_t count = 0;
+
+ length = strlen (data);
+ for (offset = 0; offset < length; offset++)
+ {
+ switch (data[offset])
+ {
+ case '%': case '\n': case '\r':
+ count++;
+ break;
+ default:
+ break;
+ }
+ }
+
+ buffer_length = length + count * 2;
+ buffer = malloc (buffer_length + 1);
+ if (!buffer)
+ return NULL;
+
+ out_p = buffer;
+ for (offset = 0; offset < length; offset++)
+ {
+ int c = data[offset];
+ switch (c)
+ {
+ case '%': case '\n': case '\r':
+ sprintf (out_p, "%%%02X", c);
+ out_p += 3;
+ break;
+ default:
+ *out_p++ = c;
+ break;
+ }
+ }
+ *out_p = '\0';
+
+ return buffer;
+}
+
+/* The inverse of escape. Unlike escape, it removes quoting in string
+ DATA by modifying the string in place, to avoid copying of secret
+ data sent from Emacs. */
+static char *
+unescape (char *data)
+{
+ char *p = data, *q = data;
+
+ while (*p)
+ {
+ if (*p == '%' && p[1] && p[2])
+ {
+ p++;
+ *q++ = xtoi_2 (p);
+ p += 2;
+ }
+ else
+ *q++ = *p++;
+ }
+ *q = 0;
+ return data;
+}
+
+/* Let's send the data to Emacs when either
+ - the data ends in "\n", or
+ - the buffer is full (but this shouldn't happen)
+ Otherwise, we just accumulate it. */
+static int
+send_to_emacs (int s, const char *buffer)
+{
+ size_t length;
+
+ length = strlen (buffer);
+ while (*buffer)
+ {
+ size_t part = MIN (length, SEND_BUFFER_SIZE - send_buffer_length);
+ memcpy (&send_buffer[send_buffer_length], buffer, part);
+ buffer += part;
+ send_buffer_length += part;
+
+ if (send_buffer_length == SEND_BUFFER_SIZE
+ || (send_buffer_length > 0
+ && send_buffer[send_buffer_length-1] == '\n'))
+ {
+ int sent = send (s, send_buffer, send_buffer_length, 0);
+ if (sent < 0)
+ {
+ fprintf (stderr, "failed to send %d bytes to socket: %s\n",
+ send_buffer_length, strerror (errno));
+ send_buffer_length = 0;
+ return 0;
+ }
+ if (sent != send_buffer_length)
+ memmove (send_buffer, &send_buffer[sent],
+ send_buffer_length - sent);
+ send_buffer_length -= sent;
+ }
+
+ length -= part;
+ }
+
+ return 1;
+}
+
+/* Read a server response. If the response contains data, it will be
+ stored in BUFFER with a terminating NUL byte. BUFFER must be
+ at least as large as CAPACITY. */
+static gpg_error_t
+read_from_emacs (int s, int timeout, char *buffer, size_t capacity)
+{
+ struct timeval tv;
+ fd_set rfds;
+ int retval;
+ /* Offset in BUFFER. */
+ size_t offset = 0;
+ int got_response = 0;
+ char read_buffer[LINELENGTH + 1];
+ /* Offset in READ_BUFFER. */
+ size_t read_offset = 0;
+ gpg_error_t result = 0;
+
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+
+ FD_ZERO (&rfds);
+ FD_SET (s, &rfds);
+ retval = select (s + 1, &rfds, NULL, NULL, &tv);
+ if (retval == -1)
+ {
+ perror ("select");
+ return gpg_error (GPG_ERR_ASS_GENERAL);
+ }
+ else if (retval == 0)
+ {
+ timed_out = 1;
+ return gpg_error (GPG_ERR_TIMEOUT);
+ }
+
+ /* Loop until we get either OK or ERR. */
+ while (!got_response)
+ {
+ int rl = 0;
+ char *p, *end_p;
+ do
+ {
+ errno = 0;
+ rl = recv (s, read_buffer + read_offset, LINELENGTH - read_offset, 0);
+ }
+ /* If we receive a signal (e.g. SIGWINCH, which we pass
+ through to Emacs), on some OSes we get EINTR and must retry. */
+ while (rl < 0 && errno == EINTR);
+
+ if (rl < 0)
+ {
+ perror ("recv");
+ return gpg_error (GPG_ERR_ASS_GENERAL);;
+ }
+ if (rl == 0)
+ break;
+
+ read_offset += rl;
+ read_buffer[read_offset] = '\0';
+
+ end_p = strchr (read_buffer, '\n');
+
+ /* If the buffer is filled without NL, throw away the content
+ and start over the buffering.
+
+ FIXME: We could return ASSUAN_Line_Too_Long or
+ ASSUAN_Line_Not_Terminated here. */
+ if (!end_p && read_offset == sizeof (read_buffer) - 1)
+ {
+ read_offset = 0;
+ continue;
+ }
+
+ /* Loop over all NL-terminated messages. */
+ for (p = read_buffer; end_p; p = end_p + 1, end_p = strchr (p, '\n'))
+ {
+ *end_p = '\0';
+ if (!strncmp ("D ", p, 2))
+ {
+ char *data;
+ size_t data_length;
+ size_t needed_capacity;
+
+ data = p + 2;
+ data_length = end_p - data;
+ if (data_length > 0)
+ {
+ needed_capacity = offset + data_length + 1;
+
+ /* Check overflow. This is unrealistic but can
+ happen since OFFSET is cumulative. */
+ if (needed_capacity < offset)
+ return gpg_error (GPG_ERR_ASS_GENERAL);;
+
+ if (needed_capacity > capacity)
+ return gpg_error (GPG_ERR_ASS_GENERAL);;
+
+ memcpy (&buffer[offset], data, data_length);
+ offset += data_length;
+ buffer[offset] = 0;
+ }
+ }
+ else if (!strcmp ("OK", p) || !strncmp ("OK ", p, 3))
+ {
+ got_response = 1;
+ break;
+ }
+ else if (!strncmp ("ERR ", p, 4))
+ {
+ unsigned long code = strtoul (p + 4, NULL, 10);
+ if (code == ULONG_MAX && errno == ERANGE)
+ return gpg_error (GPG_ERR_ASS_GENERAL);
+ else
+ result = code;
+ got_response = 1;
+ break;
+ }
+ else if (*p == '#')
+ ;
+ else
+ fprintf (stderr, "invalid response: %s\n", p);
+ }
+
+ if (!got_response)
+ {
+ size_t length = &read_buffer[read_offset] - p;
+ memmove (read_buffer, p, length);
+ read_offset = length;
+ }
+ }
+
+ return result;
+}
+
+int
+set_label (pinentry_t pe, const char *name, const char *value)
+{
+ char buffer[16], *escaped;
+ gpg_error_t error;
+ int retval;
+
+ if (!send_to_emacs (emacs_socket, name)
+ || !send_to_emacs (emacs_socket, " "))
+ return 0;
+
+ escaped = escape (value);
+ if (!escaped)
+ return 0;
+
+ retval = send_to_emacs (emacs_socket, escaped)
+ && send_to_emacs (emacs_socket, "\n");
+
+ free (escaped);
+ if (!retval)
+ return 0;
+
+ error = read_from_emacs (emacs_socket, pe->timeout, buffer, sizeof (buffer));
+ return error == 0;
+}
+
+static void
+set_labels (pinentry_t pe)
+{
+ char *p;
+
+ p = pinentry_get_title (pe);
+ if (p)
+ {
+ set_label (pe, "SETTITLE", p);
+ free (p);
+ }
+ if (pe->description)
+ set_label (pe, "SETDESC", pe->description);
+ if (pe->error)
+ set_label (pe, "SETERROR", pe->error);
+ if (pe->prompt)
+ set_label (pe, "SETPROMPT", pe->prompt);
+ else if (pe->default_prompt)
+ set_label (pe, "SETPROMPT", pe->default_prompt);
+ if (pe->repeat_passphrase)
+ set_label (pe, "SETREPEAT", pe->repeat_passphrase);
+ if (pe->repeat_error_string)
+ set_label (pe, "SETREPEATERROR", pe->repeat_error_string);
+
+ /* XXX: pe->quality_bar and pe->quality_bar_tt are not supported. */
+
+ /* Buttons. */
+ if (pe->ok)
+ set_label (pe, "SETOK", pe->ok);
+ else if (pe->default_ok)
+ set_label (pe, "SETOK", pe->default_ok);
+ if (pe->cancel)
+ set_label (pe, "SETCANCEL", pe->cancel);
+ else if (pe->default_cancel)
+ set_label (pe, "SETCANCEL", pe->default_cancel);
+ if (pe->notok)
+ set_label (pe, "SETNOTOK", pe->notok);
+}
+
+static int
+do_password (pinentry_t pe)
+{
+ char *buffer, *password;
+ size_t length = LINELENGTH;
+ gpg_error_t error;
+
+ set_labels (pe);
+
+ if (!send_to_emacs (emacs_socket, "GETPIN\n"))
+ return -1;
+
+ buffer = secmem_malloc (length);
+ if (!buffer)
+ {
+ pe->specific_err = gpg_error (GPG_ERR_ENOMEM);
+ return -1;
+ }
+
+ error = read_from_emacs (emacs_socket, pe->timeout, buffer, length);
+ if (error != 0)
+ {
+ if (gpg_err_code (error) == GPG_ERR_CANCELED)
+ pe->canceled = 1;
+
+ secmem_free (buffer);
+ pe->specific_err = error;
+ return -1;
+ }
+
+ password = unescape (buffer);
+ pinentry_setbufferlen (pe, strlen (password) + 1);
+ if (pe->pin)
+ strcpy (pe->pin, password);
+ secmem_free (buffer);
+
+ if (pe->repeat_passphrase)
+ pe->repeat_okay = 1;
+
+ /* XXX: we don't support external password cache (yet). */
+
+ return 1;
+}
+
+static int
+do_confirm (pinentry_t pe)
+{
+ char buffer[16];
+ gpg_error_t error;
+
+ set_labels (pe);
+
+ if (!send_to_emacs (emacs_socket, "CONFIRM\n"))
+ return 0;
+
+ error = read_from_emacs (emacs_socket, pe->timeout, buffer, sizeof (buffer));
+ if (error != 0)
+ {
+ if (gpg_err_code (error) == GPG_ERR_CANCELED)
+ pe->canceled = 1;
+
+ pe->specific_err = error;
+ return 0;
+ }
+
+ return 1;
+}
+
+/* If a touch has been registered, touch that file. */
+static void
+do_touch_file (pinentry_t pinentry)
+{
+#ifdef HAVE_UTIME_H
+ struct stat st;
+ time_t tim;
+
+ if (!pinentry->touch_file || !*pinentry->touch_file)
+ return;
+
+ if (stat (pinentry->touch_file, &st))
+ return; /* Oops. */
+
+ /* Make sure that we actually update the mtime. */
+ while ( (tim = time (NULL)) == st.st_mtime )
+ sleep (1);
+
+ /* Update but ignore errors as we can't do anything in that case.
+ Printing error messages may even clubber the display further. */
+ utime (pinentry->touch_file, NULL);
+#endif /*HAVE_UTIME_H*/
+}
+
+#ifndef HAVE_DOSISH_SYSTEM
+static void
+catchsig (int sig)
+{
+ if (sig == SIGALRM)
+ timed_out = 1;
+}
+#endif
+
+int
+emacs_cmd_handler (pinentry_t pe)
+{
+ int rc;
+
+#ifndef HAVE_DOSISH_SYSTEM
+ timed_out = 0;
+
+ if (pe->timeout)
+ {
+ struct sigaction sa;
+
+ memset (&sa, 0, sizeof(sa));
+ sa.sa_handler = catchsig;
+ sigaction (SIGALRM, &sa, NULL);
+ alarm (pe->timeout);
+ }
+#endif
+
+ if (pe->pin)
+ rc = do_password (pe);
+ else
+ rc = do_confirm (pe);
+
+ do_touch_file (pe);
+ return rc;
+}
+
+static int
+initial_emacs_cmd_handler (pinentry_t pe)
+{
+ /* Let the select() call in pinentry_emacs_init honor the timeout
+ value set through an Assuan option. */
+ initial_timeout = pe->timeout;
+
+ if (emacs_socket < 0)
+ pinentry_emacs_init ();
+
+ /* If we have successfully connected to Emacs, swap
+ pinentry_cmd_handler to emacs_cmd_handler, so further
+ interactions will be forwarded to Emacs. Otherwise, set it back
+ to the original command handler saved as
+ fallback_cmd_handler. */
+ if (emacs_socket < 0)
+ pinentry_cmd_handler = fallback_cmd_handler;
+ else
+ {
+ pinentry_cmd_handler = emacs_cmd_handler;
+ pinentry_set_flavor_flag ("emacs");
+ }
+
+ return (* pinentry_cmd_handler) (pe);
+}
+
+void
+pinentry_enable_emacs_cmd_handler (void)
+{
+ const char *envvar;
+
+ /* Check if pinentry_cmd_handler is already prepared for Emacs. */
+ if (pinentry_cmd_handler == initial_emacs_cmd_handler
+ || pinentry_cmd_handler == emacs_cmd_handler)
+ return;
+
+ /* Check if INSIDE_EMACS envvar is set. */
+ envvar = getenv ("INSIDE_EMACS");
+ if (!envvar || !*envvar)
+ return;
+
+ /* Save the original command handler as fallback_cmd_handler, and
+ swap pinentry_cmd_handler to initial_emacs_cmd_handler. */
+ fallback_cmd_handler = pinentry_cmd_handler;
+ pinentry_cmd_handler = initial_emacs_cmd_handler;
+}
+
+
+/* Returns true if the Emacs pinentry is enabled. The value is 1
+ * before the first connection with Emacs has been done and 2 if the
+ * connection to Emacs has been establish. Returns false if the Emacs
+ * pinentry is not enabled. */
+int
+pinentry_emacs_status (void)
+{
+ if (pinentry_cmd_handler == initial_emacs_cmd_handler)
+ return 1;
+ else if (pinentry_cmd_handler == emacs_cmd_handler)
+ return 2;
+ else
+ return 0;
+}
+
+int
+pinentry_emacs_init (void)
+{
+ char buffer[256];
+ gpg_error_t error;
+
+ assert (emacs_socket < 0);
+
+ /* Check if we can connect to the Emacs server socket. */
+ if (!set_socket ("pinentry"))
+ return 0;
+
+ /* Check if the server responds. */
+ error = read_from_emacs (emacs_socket, initial_timeout,
+ buffer, sizeof (buffer));
+ if (error != 0)
+ {
+ close (emacs_socket);
+ emacs_socket = -1;
+ return 0;
+ }
+ return 1;
+}
diff --git a/debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/pinentry-emacs.h b/debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/pinentry-emacs.h
new file mode 100644
index 00000000..b05d53bc
--- /dev/null
+++ b/debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/pinentry-emacs.h
@@ -0,0 +1,47 @@
+/* pinentry-emacs.c - A secure emacs dialog for PIN entry, library version
+ * Copyright (C) 2015 Daiki Ueno
+ *
+ * This file is part of PINENTRY.
+ *
+ * PINENTRY 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.
+ *
+ * PINENTRY 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/>.
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef PINENTRY_EMACS_H
+#define PINENTRY_EMACS_H
+
+#include "pinentry.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Enable pinentry command handler which interacts with Emacs, if
+ INSIDE_EMACS envvar is set. This function shall be called upon
+ receiving an Assuan request "OPTION allow-emacs-prompt". */
+void pinentry_enable_emacs_cmd_handler (void);
+
+/* Return info on whether emacs support is enabled. */
+int pinentry_emacs_status (void);
+
+/* Initialize the Emacs interface, return true if success. */
+int pinentry_emacs_init (void);
+
+int emacs_cmd_handler (pinentry_t pinentry);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PINENTRY_EMACS_H */
diff --git a/debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/pinentry.c b/debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/pinentry.c
new file mode 100644
index 00000000..ea11b67f
--- /dev/null
+++ b/debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/pinentry.c
@@ -0,0 +1,2067 @@
+/* pinentry.c - The PIN entry support library
+ * Copyright (C) 2002, 2003, 2007, 2008, 2010, 2015, 2016, 2021 g10 Code GmbH
+ *
+ * This file is part of PINENTRY.
+ *
+ * PINENTRY 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.
+ *
+ * PINENTRY 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/>.
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef HAVE_W32CE_SYSTEM
+# include <errno.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <assert.h>
+#ifndef HAVE_W32_SYSTEM
+# include <sys/utsname.h>
+#endif
+#ifndef HAVE_W32CE_SYSTEM
+# include <locale.h>
+#endif
+#include <limits.h>
+#ifdef HAVE_W32CE_SYSTEM
+# include <windows.h>
+#endif
+
+#include <assuan.h>
+
+#include "memory.h"
+#include "secmem-util.h"
+#include "argparse.h"
+#include "pinentry.h"
+#include "password-cache.h"
+
+#ifdef INSIDE_EMACS
+# include "pinentry-emacs.h"
+#endif
+#ifdef FALLBACK_CURSES
+# include "pinentry-curses.h"
+#endif
+
+#ifdef HAVE_W32CE_SYSTEM
+#define getpid() GetCurrentProcessId ()
+#endif
+
+/* Keep the name of our program here. */
+static char this_pgmname[50];
+
+struct pinentry pinentry;
+
+
+static const char *flavor_flag;
+
+/* Because gtk_init removes the --display arg from the command lines
+ * and our command line parser is called after gtk_init (so that it
+ * does not see gtk specific options) we don't have a way to get hold
+ * of the --display option. Our solution is to remember --display in
+ * the call to pinentry_have_display and set it then in our
+ * parser. */
+static char *remember_display;
+
+static void
+pinentry_reset (int use_defaults)
+{
+ /* GPG Agent sets these options once when it starts the pinentry.
+ Don't reset them. */
+ int grab = pinentry.grab;
+ char *ttyname = pinentry.ttyname;
+ char *ttytype = pinentry.ttytype_l;
+ char *ttyalert = pinentry.ttyalert;
+ char *lc_ctype = pinentry.lc_ctype;
+ char *lc_messages = pinentry.lc_messages;
+ int allow_external_password_cache = pinentry.allow_external_password_cache;
+ char *default_ok = pinentry.default_ok;
+ char *default_cancel = pinentry.default_cancel;
+ char *default_prompt = pinentry.default_prompt;
+ char *default_pwmngr = pinentry.default_pwmngr;
+ char *default_cf_visi = pinentry.default_cf_visi;
+ char *default_tt_visi = pinentry.default_tt_visi;
+ char *default_tt_hide = pinentry.default_tt_hide;
+ char *default_capshint = pinentry.default_capshint;
+ char *touch_file = pinentry.touch_file;
+ unsigned long owner_pid = pinentry.owner_pid;
+ int owner_uid = pinentry.owner_uid;
+ char *owner_host = pinentry.owner_host;
+ int constraints_enforce = pinentry.constraints_enforce;
+ char *constraints_hint_short = pinentry.constraints_hint_short;
+ char *constraints_hint_long = pinentry.constraints_hint_long;
+ char *constraints_error_title = pinentry.constraints_error_title;
+
+ /* These options are set from the command line. Don't reset
+ them. */
+ int debug = pinentry.debug;
+ char *display = pinentry.display;
+ int parent_wid = pinentry.parent_wid;
+
+ pinentry_color_t color_fg = pinentry.color_fg;
+ int color_fg_bright = pinentry.color_fg_bright;
+ pinentry_color_t color_bg = pinentry.color_bg;
+ pinentry_color_t color_so = pinentry.color_so;
+ int color_so_bright = pinentry.color_so_bright;
+
+ int timeout = pinentry.timeout;
+
+ char *invisible_char = pinentry.invisible_char;
+
+
+ /* Free any allocated memory. */
+ if (use_defaults)
+ {
+ free (pinentry.ttyname);
+ free (pinentry.ttytype_l);
+ free (pinentry.ttyalert);
+ free (pinentry.lc_ctype);
+ free (pinentry.lc_messages);
+ free (pinentry.default_ok);
+ free (pinentry.default_cancel);
+ free (pinentry.default_prompt);
+ free (pinentry.default_pwmngr);
+ free (pinentry.default_cf_visi);
+ free (pinentry.default_tt_visi);
+ free (pinentry.default_tt_hide);
+ free (pinentry.default_capshint);
+ free (pinentry.touch_file);
+ free (pinentry.owner_host);
+ free (pinentry.display);
+ free (pinentry.constraints_hint_short);
+ free (pinentry.constraints_hint_long);
+ free (pinentry.constraints_error_title);
+ }
+
+ free (pinentry.title);
+ free (pinentry.description);
+ free (pinentry.error);
+ free (pinentry.prompt);
+ free (pinentry.ok);
+ free (pinentry.notok);
+ free (pinentry.cancel);
+ secmem_free (pinentry.pin);
+ free (pinentry.repeat_passphrase);
+ free (pinentry.repeat_error_string);
+ free (pinentry.quality_bar);
+ free (pinentry.quality_bar_tt);
+ free (pinentry.formatted_passphrase_hint);
+ free (pinentry.keyinfo);
+ free (pinentry.specific_err_info);
+
+ /* Reset the pinentry structure. */
+ memset (&pinentry, 0, sizeof (pinentry));
+
+ /* Restore options without a default we want to preserve. */
+ pinentry.invisible_char = invisible_char;
+
+ /* Restore other options or set defaults. */
+
+ if (use_defaults)
+ {
+ /* Pinentry timeout in seconds. */
+ pinentry.timeout = 60;
+
+ /* Global grab. */
+ pinentry.grab = 1;
+
+ pinentry.color_fg = PINENTRY_COLOR_DEFAULT;
+ pinentry.color_fg_bright = 0;
+ pinentry.color_bg = PINENTRY_COLOR_DEFAULT;
+ pinentry.color_so = PINENTRY_COLOR_DEFAULT;
+ pinentry.color_so_bright = 0;
+
+ pinentry.owner_uid = -1;
+ }
+ else /* Restore the options. */
+ {
+ pinentry.grab = grab;
+ pinentry.ttyname = ttyname;
+ pinentry.ttytype_l = ttytype;
+ pinentry.ttyalert = ttyalert;
+ pinentry.lc_ctype = lc_ctype;
+ pinentry.lc_messages = lc_messages;
+ pinentry.allow_external_password_cache = allow_external_password_cache;
+ pinentry.default_ok = default_ok;
+ pinentry.default_cancel = default_cancel;
+ pinentry.default_prompt = default_prompt;
+ pinentry.default_pwmngr = default_pwmngr;
+ pinentry.default_cf_visi = default_cf_visi;
+ pinentry.default_tt_visi = default_tt_visi;
+ pinentry.default_tt_hide = default_tt_hide;
+ pinentry.default_capshint = default_capshint;
+ pinentry.touch_file = touch_file;
+ pinentry.owner_pid = owner_pid;
+ pinentry.owner_uid = owner_uid;
+ pinentry.owner_host = owner_host;
+ pinentry.constraints_enforce = constraints_enforce;
+ pinentry.constraints_hint_short = constraints_hint_short;
+ pinentry.constraints_hint_long = constraints_hint_long;
+ pinentry.constraints_error_title = constraints_error_title;
+
+ pinentry.debug = debug;
+ pinentry.display = display;
+ pinentry.parent_wid = parent_wid;
+
+ pinentry.color_fg = color_fg;
+ pinentry.color_fg_bright = color_fg_bright;
+ pinentry.color_bg = color_bg;
+ pinentry.color_so = color_so;
+ pinentry.color_so_bright = color_so_bright;
+
+ pinentry.timeout = timeout;
+ }
+}
+
+static gpg_error_t
+pinentry_assuan_reset_handler (assuan_context_t ctx, char *line)
+{
+ (void)ctx;
+ (void)line;
+
+ pinentry_reset (0);
+
+ return 0;
+}
+
+
+
+/* Copy TEXT or TEXTLEN to BUFFER and escape as required. Return a
+ pointer to the end of the new buffer. Note that BUFFER must be
+ large enough to keep the entire text; allocataing it 3 times of
+ TEXTLEN is sufficient. */
+static char *
+copy_and_escape (char *buffer, const void *text, size_t textlen)
+{
+ int i;
+ const unsigned char *s = (unsigned char *)text;
+ char *p = buffer;
+
+ for (i=0; i < textlen; i++)
+ {
+ if (s[i] < ' ' || s[i] == '+')
+ {
+ snprintf (p, 4, "%%%02X", s[i]);
+ p += 3;
+ }
+ else if (s[i] == ' ')
+ *p++ = '+';
+ else
+ *p++ = s[i];
+ }
+ return p;
+}
+
+
+/* Perform percent unescaping in STRING and return the new valid length
+ of the string. A terminating Nul character is inserted at the end of
+ the unescaped string.
+ */
+static size_t
+do_unescape_inplace (char *s)
+{
+ unsigned char *p, *p0;
+
+ p = p0 = s;
+ while (*s)
+ {
+ if (*s == '%' && s[1] && s[2])
+ {
+ s++;
+ *p++ = xtoi_2 (s);
+ s += 2;
+ }
+ else
+ *p++ = *s++;
+ }
+ *p = 0;
+
+ return (p - p0);
+}
+
+
+/* Return a malloced copy of the commandline for PID. If this is not
+ * possible NULL is returned. */
+#ifndef HAVE_W32_SYSTEM
+static char *
+get_cmdline (unsigned long pid)
+{
+ char buffer[200];
+ FILE *fp;
+ size_t i, n;
+
+ snprintf (buffer, sizeof buffer, "/proc/%lu/cmdline", pid);
+
+ fp = fopen (buffer, "rb");
+ if (!fp)
+ return NULL;
+ n = fread (buffer, 1, sizeof buffer - 1, fp);
+ if (n < sizeof buffer -1 && ferror (fp))
+ {
+ /* Some error occurred. */
+ fclose (fp);
+ return NULL;
+ }
+ fclose (fp);
+ if (n == 0)
+ return NULL;
+ /* Arguments are delimited by Nuls. We should do proper quoting but
+ * that can be a bit complicated, thus we simply replace the Nuls by
+ * spaces. */
+ for (i=0; i < n; i++)
+ if (!buffer[i] && i < n-1)
+ buffer[i] = ' ';
+ buffer[i] = 0; /* Make sure the last byte is the string terminator. */
+
+ return strdup (buffer);
+}
+#endif /*!HAVE_W32_SYSTEM*/
+
+
+/* Atomically ask the kernel for information about process PID.
+ * Return a malloc'ed copy of the process name as long as the process
+ * uid matches UID. If it cannot determine that the process has uid
+ * UID, it returns NULL.
+ *
+ * This is not as informative as get_cmdline, but it verifies that the
+ * process does belong to the user in question.
+ */
+#ifndef HAVE_W32_SYSTEM
+static char *
+get_pid_name_for_uid (unsigned long pid, int uid)
+{
+ char buffer[400];
+ FILE *fp;
+ size_t end, n;
+ char *uidstr;
+
+ snprintf (buffer, sizeof buffer, "/proc/%lu/status", pid);
+
+ fp = fopen (buffer, "rb");
+ if (!fp)
+ return NULL;
+ n = fread (buffer, 1, sizeof buffer - 1, fp);
+ if (n < sizeof buffer -1 && ferror (fp))
+ {
+ /* Some error occurred. */
+ fclose (fp);
+ return NULL;
+ }
+ fclose (fp);
+ if (n == 0)
+ return NULL;
+ buffer[n] = 0;
+ /* Fixme: Is it specified that "Name" is always the first line? For
+ * robustness I would prefer to have a real parser here. -wk */
+ if (strncmp (buffer, "Name:\t", 6))
+ return NULL;
+ end = strcspn (buffer + 6, "\n") + 6;
+ buffer[end] = 0;
+
+ /* check that uid matches what we expect */
+ uidstr = strstr (buffer + end + 1, "\nUid:\t");
+ if (!uidstr)
+ return NULL;
+ if (atoi (uidstr + 6) != uid)
+ return NULL;
+
+ return strdup (buffer + 6);
+}
+#endif /*!HAVE_W32_SYSTEM*/
+
+
+const char *
+pinentry_get_pgmname (void)
+{
+ return this_pgmname;
+}
+
+
+/* Return a malloced string with the title. The caller mus free the
+ * string. If no title is available or the title string has an error
+ * NULL is returned. */
+char *
+pinentry_get_title (pinentry_t pe)
+{
+ char *title;
+
+ if (pe->title)
+ title = strdup (pe->title);
+#ifndef HAVE_W32_SYSTEM
+ else if (pe->owner_pid)
+ {
+ char buf[200];
+ struct utsname utsbuf;
+ char *pidname = NULL;
+ char *cmdline = NULL;
+
+ if (pe->owner_host &&
+ !uname (&utsbuf) &&
+ !strcmp (utsbuf.nodename, pe->owner_host))
+ {
+ pidname = get_pid_name_for_uid (pe->owner_pid, pe->owner_uid);
+ if (pidname)
+ cmdline = get_cmdline (pe->owner_pid);
+ }
+
+ if (pe->owner_host && (cmdline || pidname))
+ snprintf (buf, sizeof buf, "[%lu]@%s (%s)",
+ pe->owner_pid, pe->owner_host, cmdline ? cmdline : pidname);
+ else if (pe->owner_host)
+ snprintf (buf, sizeof buf, "[%lu]@%s",
+ pe->owner_pid, pe->owner_host);
+ else
+ snprintf (buf, sizeof buf, "[%lu] <unknown host>",
+ pe->owner_pid);
+ free (pidname);
+ free (cmdline);
+ title = strdup (buf);
+ }
+#endif /*!HAVE_W32_SYSTEM*/
+ else
+ title = strdup (this_pgmname);
+
+ return title;
+}
+
+
+/* Run a quality inquiry for PASSPHRASE of LENGTH. (We need LENGTH
+ because not all backends might be able to return a proper
+ C-string.). Returns: A value between -100 and 100 to give an
+ estimate of the passphrase's quality. Negative values are use if
+ the caller won't even accept that passphrase. Note that we expect
+ just one data line which should not be escaped in any represent a
+ numeric signed decimal value. Extra data is currently ignored but
+ should not be send at all. */
+int
+pinentry_inq_quality (pinentry_t pin, const char *passphrase, size_t length)
+{
+ assuan_context_t ctx = pin->ctx_assuan;
+ const char prefix[] = "INQUIRE QUALITY ";
+ char *command;
+ char *line;
+ size_t linelen;
+ int gotvalue = 0;
+ int value = 0;
+ int rc;
+
+ if (!ctx)
+ return 0; /* Can't run the callback. */
+
+ if (length > 300)
+ length = 300; /* Limit so that it definitely fits into an Assuan
+ line. */
+
+ command = secmem_malloc (strlen (prefix) + 3*length + 1);
+ if (!command)
+ return 0;
+ strcpy (command, prefix);
+ copy_and_escape (command + strlen(command), passphrase, length);
+ rc = assuan_write_line (ctx, command);
+ secmem_free (command);
+ if (rc)
+ {
+ fprintf (stderr, "ASSUAN WRITE LINE failed: rc=%d\n", rc);
+ return 0;
+ }
+
+ for (;;)
+ {
+ do
+ {
+ rc = assuan_read_line (ctx, &line, &linelen);
+ if (rc)
+ {
+ fprintf (stderr, "ASSUAN READ LINE failed: rc=%d\n", rc);
+ return 0;
+ }
+ }
+ while (*line == '#' || !linelen);
+ if (line[0] == 'E' && line[1] == 'N' && line[2] == 'D'
+ && (!line[3] || line[3] == ' '))
+ break; /* END command received*/
+ if (line[0] == 'C' && line[1] == 'A' && line[2] == 'N'
+ && (!line[3] || line[3] == ' '))
+ break; /* CAN command received*/
+ if (line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
+ && (!line[3] || line[3] == ' '))
+ break; /* ERR command received*/
+ if (line[0] != 'D' || line[1] != ' ' || linelen < 3 || gotvalue)
+ continue;
+ gotvalue = 1;
+ value = atoi (line+2);
+ }
+ if (value < -100)
+ value = -100;
+ else if (value > 100)
+ value = 100;
+
+ return value;
+}
+
+
+/* Run a checkpin inquiry */
+char *
+pinentry_inq_checkpin (pinentry_t pin, const char *passphrase, size_t length)
+{
+ assuan_context_t ctx = pin->ctx_assuan;
+ const char prefix[] = "INQUIRE CHECKPIN ";
+ char *command;
+ char *line;
+ size_t linelen;
+ int gotvalue = 0;
+ char *value = NULL;
+ int rc;
+
+ if (!ctx)
+ return 0; /* Can't run the callback. */
+
+ if (length > 300)
+ length = 300; /* Limit so that it definitely fits into an Assuan
+ line. */
+
+ command = secmem_malloc (strlen (prefix) + 3*length + 1);
+ if (!command)
+ return 0;
+ strcpy (command, prefix);
+ copy_and_escape (command + strlen(command), passphrase, length);
+ rc = assuan_write_line (ctx, command);
+ secmem_free (command);
+ if (rc)
+ {
+ fprintf (stderr, "ASSUAN WRITE LINE failed: rc=%d\n", rc);
+ return 0;
+ }
+
+ for (;;)
+ {
+ do
+ {
+ rc = assuan_read_line (ctx, &line, &linelen);
+ if (rc)
+ {
+ fprintf (stderr, "ASSUAN READ LINE failed: rc=%d\n", rc);
+ return 0;
+ }
+ }
+ while (*line == '#' || !linelen);
+ if (line[0] == 'E' && line[1] == 'N' && line[2] == 'D'
+ && (!line[3] || line[3] == ' '))
+ break; /* END command received*/
+ if (line[0] == 'C' && line[1] == 'A' && line[2] == 'N'
+ && (!line[3] || line[3] == ' '))
+ break; /* CAN command received*/
+ if (line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
+ && (!line[3] || line[3] == ' '))
+ break; /* ERR command received*/
+ if (line[0] != 'D' || line[1] != ' ' || linelen < 3 || gotvalue)
+ continue;
+ gotvalue = 1;
+ value = strdup (line + 2);
+ }
+
+ return value;
+}
+
+
+/* Run a genpin inquiry */
+char *
+pinentry_inq_genpin (pinentry_t pin)
+{
+ assuan_context_t ctx = pin->ctx_assuan;
+ const char prefix[] = "INQUIRE GENPIN";
+ char *line;
+ size_t linelen;
+ int gotvalue = 0;
+ char *value = NULL;
+ int rc;
+
+ if (!ctx)
+ return 0; /* Can't run the callback. */
+
+ rc = assuan_write_line (ctx, prefix);
+ if (rc)
+ {
+ fprintf (stderr, "ASSUAN WRITE LINE failed: rc=%d\n", rc);
+ return 0;
+ }
+
+ for (;;)
+ {
+ do
+ {
+ rc = assuan_read_line (ctx, &line, &linelen);
+ if (rc)
+ {
+ fprintf (stderr, "ASSUAN READ LINE failed: rc=%d\n", rc);
+ free (value);
+ return 0;
+ }
+ }
+ while (*line == '#' || !linelen);
+ if (line[0] == 'E' && line[1] == 'N' && line[2] == 'D'
+ && (!line[3] || line[3] == ' '))
+ break; /* END command received*/
+ if (line[0] == 'C' && line[1] == 'A' && line[2] == 'N'
+ && (!line[3] || line[3] == ' '))
+ break; /* CAN command received*/
+ if (line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
+ && (!line[3] || line[3] == ' '))
+ break; /* ERR command received*/
+ if (line[0] != 'D' || line[1] != ' ' || linelen < 3 || gotvalue)
+ continue;
+ gotvalue = 1;
+ value = strdup (line + 2);
+ }
+
+ return value;
+}
+
+/* Try to make room for at least LEN bytes in the pinentry. Returns
+ new buffer on success and 0 on failure or when the old buffer is
+ sufficient. */
+char *
+pinentry_setbufferlen (pinentry_t pin, int len)
+{
+ char *newp;
+
+ if (pin->pin_len)
+ assert (pin->pin);
+ else
+ assert (!pin->pin);
+
+ if (len < 2048)
+ len = 2048;
+
+ if (len <= pin->pin_len)
+ return pin->pin;
+
+ newp = secmem_realloc (pin->pin, len);
+ if (newp)
+ {
+ pin->pin = newp;
+ pin->pin_len = len;
+ }
+ else
+ {
+ secmem_free (pin->pin);
+ pin->pin = 0;
+ pin->pin_len = 0;
+ }
+ return newp;
+}
+
+static void
+pinentry_setbuffer_clear (pinentry_t pin)
+{
+ if (! pin->pin)
+ {
+ assert (pin->pin_len == 0);
+ return;
+ }
+
+ assert (pin->pin_len > 0);
+
+ secmem_free (pin->pin);
+ pin->pin = NULL;
+ pin->pin_len = 0;
+}
+
+static void
+pinentry_setbuffer_init (pinentry_t pin)
+{
+ pinentry_setbuffer_clear (pin);
+ pinentry_setbufferlen (pin, 0);
+}
+
+/* passphrase better be alloced with secmem_alloc. */
+void
+pinentry_setbuffer_use (pinentry_t pin, char *passphrase, int len)
+{
+ if (! passphrase)
+ {
+ assert (len == 0);
+ pinentry_setbuffer_clear (pin);
+
+ return;
+ }
+
+ if (passphrase && len == 0)
+ len = strlen (passphrase) + 1;
+
+ if (pin->pin)
+ secmem_free (pin->pin);
+
+ pin->pin = passphrase;
+ pin->pin_len = len;
+}
+
+static struct assuan_malloc_hooks assuan_malloc_hooks = {
+ secmem_malloc, secmem_realloc, secmem_free
+};
+
+/* Initialize the secure memory subsystem, drop privileges and return.
+ Must be called early. */
+void
+pinentry_init (const char *pgmname)
+{
+ /* Store away our name. */
+ if (strlen (pgmname) > sizeof this_pgmname - 2)
+ abort ();
+ strcpy (this_pgmname, pgmname);
+
+ gpgrt_check_version (NULL);
+
+ /* Initialize secure memory. 1 is too small, so the default size
+ will be used. */
+ secmem_init (1);
+ secmem_set_flags (SECMEM_WARN);
+ drop_privs ();
+
+ if (atexit (secmem_term))
+ {
+ /* FIXME: Could not register at-exit function, bail out. */
+ }
+
+ assuan_set_malloc_hooks (&assuan_malloc_hooks);
+}
+
+/* Simple test to check whether DISPLAY is set or the option --display
+ was given. Used to decide whether the GUI or curses should be
+ initialized. */
+int
+pinentry_have_display (int argc, char **argv)
+{
+ int found = 0;
+
+ for (; argc; argc--, argv++)
+ {
+ if (!strcmp (*argv, "--display"))
+ {
+ if (argv[1] && !remember_display)
+ {
+ remember_display = strdup (argv[1]);
+ if (!remember_display)
+ {
+#ifndef HAVE_W32CE_SYSTEM
+ fprintf (stderr, "%s: %s\n", this_pgmname, strerror (errno));
+#endif
+ exit (EXIT_FAILURE);
+ }
+ }
+ found = 1;
+ break;
+ }
+ else if (!strncmp (*argv, "--display=", 10))
+ {
+ if (!remember_display)
+ {
+ remember_display = strdup (*argv+10);
+ if (!remember_display)
+ {
+#ifndef HAVE_W32CE_SYSTEM
+ fprintf (stderr, "%s: %s\n", this_pgmname, strerror (errno));
+#endif
+ exit (EXIT_FAILURE);
+ }
+ }
+ found = 1;
+ break;
+ }
+ }
+
+#ifndef HAVE_W32CE_SYSTEM
+ {
+ const char *s;
+ s = getenv ("DISPLAY");
+ if (s && *s)
+ found = 1;
+ }
+#endif
+
+ return found;
+}
+
+
+
+/* Print usage information and and provide strings for help. */
+static const char *
+my_strusage( int level )
+{
+ const char *p;
+
+ switch (level)
+ {
+ case 11: p = this_pgmname; break;
+ case 12: p = "pinentry"; break;
+ case 13: p = PACKAGE_VERSION; break;
+ case 14: p = "Copyright (C) 2016 g10 Code GmbH"; break;
+ case 19: p = "Please report bugs to <" PACKAGE_BUGREPORT ">.\n"; break;
+ case 1:
+ case 40:
+ {
+ static char *str;
+
+ if (!str)
+ {
+ size_t n = 50 + strlen (this_pgmname);
+ str = malloc (n);
+ if (str)
+ {
+ snprintf (str, n, "Usage: %s [options] (-h for help)",
+ this_pgmname);
+ }
+ }
+ p = str;
+ }
+ break;
+ case 41:
+ p = "Ask securely for a secret and print it to stdout.";
+ break;
+
+ case 42:
+ p = "1"; /* Flag print 40 as part of 41. */
+ break;
+
+ default: p = NULL; break;
+ }
+ return p;
+}
+
+
+char *
+parse_color (char *arg, pinentry_color_t *color_p, int *bright_p)
+{
+ static struct
+ {
+ const char *name;
+ pinentry_color_t color;
+ } colors[] = { { "none", PINENTRY_COLOR_NONE },
+ { "default", PINENTRY_COLOR_DEFAULT },
+ { "black", PINENTRY_COLOR_BLACK },
+ { "red", PINENTRY_COLOR_RED },
+ { "green", PINENTRY_COLOR_GREEN },
+ { "yellow", PINENTRY_COLOR_YELLOW },
+ { "blue", PINENTRY_COLOR_BLUE },
+ { "magenta", PINENTRY_COLOR_MAGENTA },
+ { "cyan", PINENTRY_COLOR_CYAN },
+ { "white", PINENTRY_COLOR_WHITE } };
+
+ int i;
+ char *new_arg;
+ pinentry_color_t color = PINENTRY_COLOR_DEFAULT;
+
+ if (!arg)
+ return NULL;
+
+ new_arg = strchr (arg, ',');
+ if (new_arg)
+ new_arg++;
+
+ if (bright_p)
+ {
+ const char *bname[] = { "bright-", "bright", "bold-", "bold" };
+
+ *bright_p = 0;
+ for (i = 0; i < sizeof (bname) / sizeof (bname[0]); i++)
+ if (!strncasecmp (arg, bname[i], strlen (bname[i])))
+ {
+ *bright_p = 1;
+ arg += strlen (bname[i]);
+ }
+ }
+
+ for (i = 0; i < sizeof (colors) / sizeof (colors[0]); i++)
+ if (!strncasecmp (arg, colors[i].name, strlen (colors[i].name)))
+ color = colors[i].color;
+
+ *color_p = color;
+ return new_arg;
+}
+
+/* Parse the command line options. May exit the program if only help
+ or version output is requested. */
+void
+pinentry_parse_opts (int argc, char *argv[])
+{
+ static ARGPARSE_OPTS opts[] = {
+ ARGPARSE_s_n('d', "debug", "Turn on debugging output"),
+ ARGPARSE_s_s('D', "display", "|DISPLAY|Set the X display"),
+ ARGPARSE_s_s('T', "ttyname", "|FILE|Set the tty terminal node name"),
+ ARGPARSE_s_s('N', "ttytype", "|NAME|Set the tty terminal type"),
+ ARGPARSE_s_s('C', "lc-ctype", "|STRING|Set the tty LC_CTYPE value"),
+ ARGPARSE_s_s('M', "lc-messages", "|STRING|Set the tty LC_MESSAGES value"),
+ ARGPARSE_s_i('o', "timeout",
+ "|SECS|Timeout waiting for input after this many seconds"),
+ ARGPARSE_s_n('g', "no-global-grab",
+ "Grab keyboard only while window is focused"),
+ ARGPARSE_s_u('W', "parent-wid", "Parent window ID (for positioning)"),
+ ARGPARSE_s_s('c', "colors", "|STRING|Set custom colors for ncurses"),
+ ARGPARSE_s_s('a', "ttyalert", "|STRING|Set the alert mode (none, beep or flash)"),
+ ARGPARSE_end()
+ };
+ ARGPARSE_ARGS pargs = { &argc, &argv, 0 };
+
+ set_strusage (my_strusage);
+
+ pinentry_reset (1);
+
+ while (arg_parse (&pargs, opts))
+ {
+ switch (pargs.r_opt)
+ {
+ case 'd':
+ pinentry.debug = 1;
+ break;
+ case 'g':
+ pinentry.grab = 0;
+ break;
+
+ case 'D':
+ /* Note, this is currently not used because the GUI engine
+ has already been initialized when parsing these options. */
+ pinentry.display = strdup (pargs.r.ret_str);
+ if (!pinentry.display)
+ {
+#ifndef HAVE_W32CE_SYSTEM
+ fprintf (stderr, "%s: %s\n", this_pgmname, strerror (errno));
+#endif
+ exit (EXIT_FAILURE);
+ }
+ break;
+ case 'T':
+ pinentry.ttyname = strdup (pargs.r.ret_str);
+ if (!pinentry.ttyname)
+ {
+#ifndef HAVE_W32CE_SYSTEM
+ fprintf (stderr, "%s: %s\n", this_pgmname, strerror (errno));
+#endif
+ exit (EXIT_FAILURE);
+ }
+ break;
+ case 'N':
+ pinentry.ttytype_l = strdup (pargs.r.ret_str);
+ if (!pinentry.ttytype_l)
+ {
+#ifndef HAVE_W32CE_SYSTEM
+ fprintf (stderr, "%s: %s\n", this_pgmname, strerror (errno));
+#endif
+ exit (EXIT_FAILURE);
+ }
+ break;
+ case 'C':
+ pinentry.lc_ctype = strdup (pargs.r.ret_str);
+ if (!pinentry.lc_ctype)
+ {
+#ifndef HAVE_W32CE_SYSTEM
+ fprintf (stderr, "%s: %s\n", this_pgmname, strerror (errno));
+#endif
+ exit (EXIT_FAILURE);
+ }
+ break;
+ case 'M':
+ pinentry.lc_messages = strdup (pargs.r.ret_str);
+ if (!pinentry.lc_messages)
+ {
+#ifndef HAVE_W32CE_SYSTEM
+ fprintf (stderr, "%s: %s\n", this_pgmname, strerror (errno));
+#endif
+ exit (EXIT_FAILURE);
+ }
+ break;
+ case 'W':
+ pinentry.parent_wid = pargs.r.ret_ulong;
+ break;
+
+ case 'c':
+ {
+ char *tmpstr = pargs.r.ret_str;
+
+ tmpstr = parse_color (tmpstr, &pinentry.color_fg,
+ &pinentry.color_fg_bright);
+ tmpstr = parse_color (tmpstr, &pinentry.color_bg, NULL);
+ tmpstr = parse_color (tmpstr, &pinentry.color_so,
+ &pinentry.color_so_bright);
+ }
+ break;
+
+ case 'o':
+ pinentry.timeout = pargs.r.ret_int;
+ break;
+
+ case 'a':
+ pinentry.ttyalert = strdup (pargs.r.ret_str);
+ if (!pinentry.ttyalert)
+ {
+#ifndef HAVE_W32CE_SYSTEM
+ fprintf (stderr, "%s: %s\n", this_pgmname, strerror (errno));
+#endif
+ exit (EXIT_FAILURE);
+ }
+ break;
+
+ default:
+ pargs.err = ARGPARSE_PRINT_WARNING;
+ break;
+ }
+ }
+
+ if (!pinentry.display && remember_display)
+ {
+ pinentry.display = remember_display;
+ remember_display = NULL;
+ }
+}
+
+
+/* Set the optional flag used with getinfo. */
+void
+pinentry_set_flavor_flag (const char *string)
+{
+ flavor_flag = string;
+}
+
+
+
+
+static gpg_error_t
+option_handler (assuan_context_t ctx, const char *key, const char *value)
+{
+ (void)ctx;
+
+ if (!strcmp (key, "no-grab") && !*value)
+ pinentry.grab = 0;
+ else if (!strcmp (key, "grab") && !*value)
+ pinentry.grab = 1;
+ else if (!strcmp (key, "debug-wait"))
+ {
+#ifndef HAVE_W32_SYSTEM
+ fprintf (stderr, "%s: waiting for debugger - my pid is %u ...\n",
+ this_pgmname, (unsigned int) getpid());
+ sleep (*value?atoi (value):5);
+ fprintf (stderr, "%s: ... okay\n", this_pgmname);
+#endif
+ }
+ else if (!strcmp (key, "display"))
+ {
+ if (pinentry.display)
+ free (pinentry.display);
+ pinentry.display = strdup (value);
+ if (!pinentry.display)
+ return gpg_error_from_syserror ();
+ }
+ else if (!strcmp (key, "ttyname"))
+ {
+ if (pinentry.ttyname)
+ free (pinentry.ttyname);
+ pinentry.ttyname = strdup (value);
+ if (!pinentry.ttyname)
+ return gpg_error_from_syserror ();
+ }
+ else if (!strcmp (key, "ttytype"))
+ {
+ if (pinentry.ttytype_l)
+ free (pinentry.ttytype_l);
+ pinentry.ttytype_l = strdup (value);
+ if (!pinentry.ttytype_l)
+ return gpg_error_from_syserror ();
+ }
+ else if (!strcmp (key, "ttyalert"))
+ {
+ if (pinentry.ttyalert)
+ free (pinentry.ttyalert);
+ pinentry.ttyalert = strdup (value);
+ if (!pinentry.ttyalert)
+ return gpg_error_from_syserror ();
+ }
+ else if (!strcmp (key, "lc-ctype"))
+ {
+ if (pinentry.lc_ctype)
+ free (pinentry.lc_ctype);
+ pinentry.lc_ctype = strdup (value);
+ if (!pinentry.lc_ctype)
+ return gpg_error_from_syserror ();
+ }
+ else if (!strcmp (key, "lc-messages"))
+ {
+ if (pinentry.lc_messages)
+ free (pinentry.lc_messages);
+ pinentry.lc_messages = strdup (value);
+ if (!pinentry.lc_messages)
+ return gpg_error_from_syserror ();
+ }
+ else if (!strcmp (key, "owner"))
+ {
+ long along;
+ char *endp;
+
+ free (pinentry.owner_host);
+ pinentry.owner_host = NULL;
+ pinentry.owner_uid = -1;
+ pinentry.owner_pid = 0;
+
+ errno = 0;
+ along = strtol (value, &endp, 10);
+ if (along && !errno)
+ {
+ pinentry.owner_pid = (unsigned long)along;
+ if (*endp)
+ {
+ errno = 0;
+ if (*endp == '/') { /* we have a uid */
+ endp++;
+ along = strtol (endp, &endp, 10);
+ if (along >= 0 && !errno)
+ pinentry.owner_uid = (int)along;
+ }
+ if (endp)
+ {
+ while (*endp == ' ')
+ endp++;
+ if (*endp)
+ {
+ pinentry.owner_host = strdup (endp);
+ for (endp=pinentry.owner_host;
+ *endp && *endp != ' '; endp++)
+ ;
+ *endp = 0;
+ }
+ }
+ }
+ }
+ }
+ else if (!strcmp (key, "parent-wid"))
+ {
+ pinentry.parent_wid = atoi (value);
+ /* FIXME: Use strtol and add some error handling. */
+ }
+ else if (!strcmp (key, "touch-file"))
+ {
+ if (pinentry.touch_file)
+ free (pinentry.touch_file);
+ pinentry.touch_file = strdup (value);
+ if (!pinentry.touch_file)
+ return gpg_error_from_syserror ();
+ }
+ else if (!strcmp (key, "default-ok"))
+ {
+ pinentry.default_ok = strdup (value);
+ if (!pinentry.default_ok)
+ return gpg_error_from_syserror ();
+ }
+ else if (!strcmp (key, "default-cancel"))
+ {
+ pinentry.default_cancel = strdup (value);
+ if (!pinentry.default_cancel)
+ return gpg_error_from_syserror ();
+ }
+ else if (!strcmp (key, "default-prompt"))
+ {
+ pinentry.default_prompt = strdup (value);
+ if (!pinentry.default_prompt)
+ return gpg_error_from_syserror ();
+ }
+ else if (!strcmp (key, "default-pwmngr"))
+ {
+ pinentry.default_pwmngr = strdup (value);
+ if (!pinentry.default_pwmngr)
+ return gpg_error_from_syserror ();
+ }
+ else if (!strcmp (key, "default-cf-visi"))
+ {
+ pinentry.default_cf_visi = strdup (value);
+ if (!pinentry.default_cf_visi)
+ return gpg_error_from_syserror ();
+ }
+ else if (!strcmp (key, "default-tt-visi"))
+ {
+ pinentry.default_tt_visi = strdup (value);
+ if (!pinentry.default_tt_visi)
+ return gpg_error_from_syserror ();
+ }
+ else if (!strcmp (key, "default-tt-hide"))
+ {
+ pinentry.default_tt_hide = strdup (value);
+ if (!pinentry.default_tt_hide)
+ return gpg_error_from_syserror ();
+ }
+ else if (!strcmp (key, "default-capshint"))
+ {
+ pinentry.default_capshint = strdup (value);
+ if (!pinentry.default_capshint)
+ return gpg_error_from_syserror ();
+ }
+ else if (!strcmp (key, "allow-external-password-cache") && !*value)
+ {
+ pinentry.allow_external_password_cache = 1;
+ pinentry.tried_password_cache = 0;
+ }
+ else if (!strcmp (key, "allow-emacs-prompt") && !*value)
+ {
+#ifdef INSIDE_EMACS
+ pinentry_enable_emacs_cmd_handler ();
+#endif
+ }
+ else if (!strcmp (key, "invisible-char"))
+ {
+ if (pinentry.invisible_char)
+ free (pinentry.invisible_char);
+ pinentry.invisible_char = strdup (value);
+ if (!pinentry.invisible_char)
+ return gpg_error_from_syserror ();
+ }
+ else if (!strcmp (key, "formatted-passphrase") && !*value)
+ {
+ pinentry.formatted_passphrase = 1;
+ }
+ else if (!strcmp (key, "formatted-passphrase-hint"))
+ {
+ if (pinentry.formatted_passphrase_hint)
+ free (pinentry.formatted_passphrase_hint);
+ pinentry.formatted_passphrase_hint = strdup (value);
+ if (!pinentry.formatted_passphrase_hint)
+ return gpg_error_from_syserror ();
+ do_unescape_inplace(pinentry.formatted_passphrase_hint);
+ }
+ else if (!strcmp (key, "constraints-enforce") && !*value)
+ pinentry.constraints_enforce = 1;
+ else if (!strcmp (key, "constraints-hint-short"))
+ {
+ if (pinentry.constraints_hint_short)
+ free (pinentry.constraints_hint_short);
+ pinentry.constraints_hint_short = strdup (value);
+ if (!pinentry.constraints_hint_short)
+ return gpg_error_from_syserror ();
+ do_unescape_inplace(pinentry.constraints_hint_short);
+ }
+ else if (!strcmp (key, "constraints-hint-long"))
+ {
+ if (pinentry.constraints_hint_long)
+ free (pinentry.constraints_hint_long);
+ pinentry.constraints_hint_long = strdup (value);
+ if (!pinentry.constraints_hint_long)
+ return gpg_error_from_syserror ();
+ do_unescape_inplace(pinentry.constraints_hint_long);
+ }
+ else if (!strcmp (key, "constraints-error-title"))
+ {
+ if (pinentry.constraints_error_title)
+ free (pinentry.constraints_error_title);
+ pinentry.constraints_error_title = strdup (value);
+ if (!pinentry.constraints_error_title)
+ return gpg_error_from_syserror ();
+ do_unescape_inplace(pinentry.constraints_error_title);
+ }
+ else
+ return gpg_error (GPG_ERR_UNKNOWN_OPTION);
+ return 0;
+}
+
+
+/* Note, that it is sufficient to allocate the target string D as
+ long as the source string S, i.e.: strlen(s)+1; */
+static void
+strcpy_escaped (char *d, const char *s)
+{
+ while (*s)
+ {
+ if (*s == '%' && s[1] && s[2])
+ {
+ s++;
+ *d++ = xtoi_2 ( s);
+ s += 2;
+ }
+ else
+ *d++ = *s++;
+ }
+ *d = 0;
+}
+
+
+static void
+write_status_error (assuan_context_t ctx, pinentry_t pe)
+{
+ char buf[500];
+ const char *pgm;
+
+ pgm = strchr (this_pgmname, '-');
+ if (pgm && pgm[1])
+ pgm++;
+ else
+ pgm = this_pgmname;
+
+ snprintf (buf, sizeof buf, "%s.%s %d %s",
+ pgm,
+ pe->specific_err_loc? pe->specific_err_loc : "?",
+ pe->specific_err,
+ pe->specific_err_info? pe->specific_err_info : "");
+ assuan_write_status (ctx, "ERROR", buf);
+}
+
+
+static gpg_error_t
+cmd_setdesc (assuan_context_t ctx, char *line)
+{
+ char *newd;
+
+ (void)ctx;
+
+ newd = malloc (strlen (line) + 1);
+ if (!newd)
+ return gpg_error_from_syserror ();
+
+ strcpy_escaped (newd, line);
+ if (pinentry.description)
+ free (pinentry.description);
+ pinentry.description = newd;
+ return 0;
+}
+
+
+static gpg_error_t
+cmd_setprompt (assuan_context_t ctx, char *line)
+{
+ char *newp;
+
+ (void)ctx;
+
+ newp = malloc (strlen (line) + 1);
+ if (!newp)
+ return gpg_error_from_syserror ();
+
+ strcpy_escaped (newp, line);
+ if (pinentry.prompt)
+ free (pinentry.prompt);
+ pinentry.prompt = newp;
+ return 0;
+}
+
+
+/* The data provided at LINE may be used by pinentry implementations
+ to identify a key for caching strategies of its own. The empty
+ string and --clear mean that the key does not have a stable
+ identifier. */
+static gpg_error_t
+cmd_setkeyinfo (assuan_context_t ctx, char *line)
+{
+ (void)ctx;
+
+ if (pinentry.keyinfo)
+ free (pinentry.keyinfo);
+
+ if (*line && strcmp(line, "--clear") != 0)
+ pinentry.keyinfo = strdup (line);
+ else
+ pinentry.keyinfo = NULL;
+
+ return 0;
+}
+
+
+static gpg_error_t
+cmd_setrepeat (assuan_context_t ctx, char *line)
+{
+ char *p;
+
+ (void)ctx;
+
+ p = malloc (strlen (line) + 1);
+ if (!p)
+ return gpg_error_from_syserror ();
+
+ strcpy_escaped (p, line);
+ free (pinentry.repeat_passphrase);
+ pinentry.repeat_passphrase = p;
+ return 0;
+}
+
+
+static gpg_error_t
+cmd_setrepeaterror (assuan_context_t ctx, char *line)
+{
+ char *p;
+
+ (void)ctx;
+
+ p = malloc (strlen (line) + 1);
+ if (!p)
+ return gpg_error_from_syserror ();
+
+ strcpy_escaped (p, line);
+ free (pinentry.repeat_error_string);
+ pinentry.repeat_error_string = p;
+ return 0;
+}
+
+
+static gpg_error_t
+cmd_seterror (assuan_context_t ctx, char *line)
+{
+ char *newe;
+
+ (void)ctx;
+
+ newe = malloc (strlen (line) + 1);
+ if (!newe)
+ return gpg_error_from_syserror ();
+
+ strcpy_escaped (newe, line);
+ if (pinentry.error)
+ free (pinentry.error);
+ pinentry.error = newe;
+ return 0;
+}
+
+
+static gpg_error_t
+cmd_setok (assuan_context_t ctx, char *line)
+{
+ char *newo;
+
+ (void)ctx;
+
+ newo = malloc (strlen (line) + 1);
+ if (!newo)
+ return gpg_error_from_syserror ();
+
+ strcpy_escaped (newo, line);
+ if (pinentry.ok)
+ free (pinentry.ok);
+ pinentry.ok = newo;
+ return 0;
+}
+
+
+static gpg_error_t
+cmd_setnotok (assuan_context_t ctx, char *line)
+{
+ char *newo;
+
+ (void)ctx;
+
+ newo = malloc (strlen (line) + 1);
+ if (!newo)
+ return gpg_error_from_syserror ();
+
+ strcpy_escaped (newo, line);
+ if (pinentry.notok)
+ free (pinentry.notok);
+ pinentry.notok = newo;
+ return 0;
+}
+
+
+static gpg_error_t
+cmd_setcancel (assuan_context_t ctx, char *line)
+{
+ char *newc;
+
+ (void)ctx;
+
+ newc = malloc (strlen (line) + 1);
+ if (!newc)
+ return gpg_error_from_syserror ();
+
+ strcpy_escaped (newc, line);
+ if (pinentry.cancel)
+ free (pinentry.cancel);
+ pinentry.cancel = newc;
+ return 0;
+}
+
+
+static gpg_error_t
+cmd_settimeout (assuan_context_t ctx, char *line)
+{
+ (void)ctx;
+
+ if (line && *line)
+ pinentry.timeout = atoi (line);
+
+ return 0;
+}
+
+static gpg_error_t
+cmd_settitle (assuan_context_t ctx, char *line)
+{
+ char *newt;
+
+ (void)ctx;
+
+ newt = malloc (strlen (line) + 1);
+ if (!newt)
+ return gpg_error_from_syserror ();
+
+ strcpy_escaped (newt, line);
+ if (pinentry.title)
+ free (pinentry.title);
+ pinentry.title = newt;
+ return 0;
+}
+
+static gpg_error_t
+cmd_setqualitybar (assuan_context_t ctx, char *line)
+{
+ char *newval;
+
+ (void)ctx;
+
+ if (!*line)
+ line = "Quality:";
+
+ newval = malloc (strlen (line) + 1);
+ if (!newval)
+ return gpg_error_from_syserror ();
+
+ strcpy_escaped (newval, line);
+ if (pinentry.quality_bar)
+ free (pinentry.quality_bar);
+ pinentry.quality_bar = newval;
+ return 0;
+}
+
+/* Set the tooltip to be used for a quality bar. */
+static gpg_error_t
+cmd_setqualitybar_tt (assuan_context_t ctx, char *line)
+{
+ char *newval;
+
+ (void)ctx;
+
+ if (*line)
+ {
+ newval = malloc (strlen (line) + 1);
+ if (!newval)
+ return gpg_error_from_syserror ();
+
+ strcpy_escaped (newval, line);
+ }
+ else
+ newval = NULL;
+ if (pinentry.quality_bar_tt)
+ free (pinentry.quality_bar_tt);
+ pinentry.quality_bar_tt = newval;
+ return 0;
+}
+
+/* Set the tooltip to be used for a generate action. */
+static gpg_error_t
+cmd_setgenpin_tt (assuan_context_t ctx, char *line)
+{
+ char *newval;
+
+ (void)ctx;
+
+ if (*line)
+ {
+ newval = malloc (strlen (line) + 1);
+ if (!newval)
+ return gpg_error_from_syserror ();
+
+ strcpy_escaped (newval, line);
+ }
+ else
+ newval = NULL;
+ if (pinentry.genpin_tt)
+ free (pinentry.genpin_tt);
+ pinentry.genpin_tt = newval;
+ return 0;
+}
+
+/* Set the label to be used for a generate action. */
+static gpg_error_t
+cmd_setgenpin_label (assuan_context_t ctx, char *line)
+{
+ char *newval;
+
+ (void)ctx;
+
+ if (*line)
+ {
+ newval = malloc (strlen (line) + 1);
+ if (!newval)
+ return gpg_error_from_syserror ();
+
+ strcpy_escaped (newval, line);
+ }
+ else
+ newval = NULL;
+ if (pinentry.genpin_label)
+ free (pinentry.genpin_label);
+ pinentry.genpin_label = newval;
+ return 0;
+}
+
+static gpg_error_t
+cmd_getpin (assuan_context_t ctx, char *line)
+{
+ int result;
+ int set_prompt = 0;
+ int just_read_password_from_cache = 0;
+
+ (void)line;
+
+ pinentry_setbuffer_init (&pinentry);
+ if (!pinentry.pin)
+ return gpg_error (GPG_ERR_ENOMEM);
+
+ /* Try reading from the password cache. */
+ if (/* If repeat passphrase is set, then we don't want to read from
+ the cache. */
+ ! pinentry.repeat_passphrase
+ /* Are we allowed to read from the cache? */
+ && pinentry.allow_external_password_cache
+ && pinentry.keyinfo
+ /* Only read from the cache if we haven't already tried it. */
+ && ! pinentry.tried_password_cache
+ /* If the last read resulted in an error, then don't read from
+ the cache. */
+ && ! pinentry.error)
+ {
+ char *password;
+ int give_up_on_password_store = 0;
+
+ pinentry.tried_password_cache = 1;
+
+ password = password_cache_lookup (pinentry.keyinfo, &give_up_on_password_store);
+ if (give_up_on_password_store)
+ pinentry.allow_external_password_cache = 0;
+
+ if (password)
+ /* There is a cached password. Try it. */
+ {
+ int len = strlen(password) + 1;
+ if (len > pinentry.pin_len)
+ len = pinentry.pin_len;
+
+ memcpy (pinentry.pin, password, len);
+ pinentry.pin[len] = '\0';
+
+ secmem_free (password);
+
+ pinentry.pin_from_cache = 1;
+
+ assuan_write_status (ctx, "PASSWORD_FROM_CACHE", "");
+
+ /* Result is the length of the password not including the
+ NUL terminator. */
+ result = len - 1;
+
+ just_read_password_from_cache = 1;
+
+ goto out;
+ }
+ }
+
+ /* The password was not cached (or we are not allowed to / cannot
+ use the cache). Prompt the user. */
+ pinentry.pin_from_cache = 0;
+
+ if (!pinentry.prompt)
+ {
+ pinentry.prompt = pinentry.default_prompt?pinentry.default_prompt:"PIN:";
+ set_prompt = 1;
+ }
+ pinentry.locale_err = 0;
+ pinentry.specific_err = 0;
+ pinentry.specific_err_loc = NULL;
+ free (pinentry.specific_err_info);
+ pinentry.specific_err_info = NULL;
+ pinentry.close_button = 0;
+ pinentry.repeat_okay = 0;
+ pinentry.one_button = 0;
+ pinentry.ctx_assuan = ctx;
+ result = (*pinentry_cmd_handler) (&pinentry);
+ pinentry.ctx_assuan = NULL;
+ if (pinentry.error)
+ {
+ free (pinentry.error);
+ pinentry.error = NULL;
+ }
+ if (pinentry.repeat_passphrase)
+ {
+ free (pinentry.repeat_passphrase);
+ pinentry.repeat_passphrase = NULL;
+ }
+ if (set_prompt)
+ pinentry.prompt = NULL;
+
+ pinentry.quality_bar = 0; /* Reset it after the command. */
+
+ if (pinentry.close_button)
+ assuan_write_status (ctx, "BUTTON_INFO", "close");
+
+ if (result < 0)
+ {
+ pinentry_setbuffer_clear (&pinentry);
+ if (pinentry.specific_err)
+ {
+ write_status_error (ctx, &pinentry);
+
+ if (gpg_err_code (pinentry.specific_err) == GPG_ERR_FULLY_CANCELED)
+ assuan_set_flag (ctx, ASSUAN_FORCE_CLOSE, 1);
+
+ return pinentry.specific_err;
+ }
+ return (pinentry.locale_err
+ ? gpg_error (GPG_ERR_LOCALE_PROBLEM)
+ : gpg_error (GPG_ERR_CANCELED));
+ }
+
+ out:
+ if (result)
+ {
+ if (pinentry.repeat_okay)
+ assuan_write_status (ctx, "PIN_REPEATED", "");
+ assuan_begin_confidential (ctx);
+ result = assuan_send_data (ctx, pinentry.pin, strlen(pinentry.pin));
+ if (!result)
+ result = assuan_send_data (ctx, NULL, 0);
+ assuan_end_confidential (ctx);
+
+ if (/* GPG Agent says it's okay. */
+ pinentry.allow_external_password_cache && pinentry.keyinfo
+ /* We didn't just read it from the cache. */
+ && ! just_read_password_from_cache
+ /* And the user said it's okay. */
+ && pinentry.may_cache_password)
+ /* Cache the password. */
+ password_cache_save (pinentry.keyinfo, pinentry.pin);
+ }
+
+ pinentry_setbuffer_clear (&pinentry);
+
+ return result;
+}
+
+
+/* Note that the option --one-button is a hack to allow the use of old
+ pinentries while the caller is ignoring the result. Given that
+ options have never been used or flagged as an error the new option
+ is an easy way to enable the messsage mode while not requiring to
+ update pinentry or to have the caller test for the message
+ command. New applications which are free to require an updated
+ pinentry should use MESSAGE instead. */
+static gpg_error_t
+cmd_confirm (assuan_context_t ctx, char *line)
+{
+ int result;
+
+ pinentry.one_button = !!strstr (line, "--one-button");
+ pinentry.quality_bar = 0;
+ pinentry.close_button = 0;
+ pinentry.locale_err = 0;
+ pinentry.specific_err = 0;
+ pinentry.specific_err_loc = NULL;
+ free (pinentry.specific_err_info);
+ pinentry.specific_err_info = NULL;
+ pinentry.canceled = 0;
+ pinentry_setbuffer_clear (&pinentry);
+ result = (*pinentry_cmd_handler) (&pinentry);
+ if (pinentry.error)
+ {
+ free (pinentry.error);
+ pinentry.error = NULL;
+ }
+
+ if (pinentry.close_button)
+ assuan_write_status (ctx, "BUTTON_INFO", "close");
+
+ if (result > 0)
+ return 0; /* OK */
+
+ if (pinentry.specific_err)
+ {
+ write_status_error (ctx, &pinentry);
+
+ if (gpg_err_code (pinentry.specific_err) == GPG_ERR_FULLY_CANCELED)
+ assuan_set_flag (ctx, ASSUAN_FORCE_CLOSE, 1);
+
+ return pinentry.specific_err;
+ }
+
+ if (pinentry.locale_err)
+ return gpg_error (GPG_ERR_LOCALE_PROBLEM);
+
+ if (pinentry.one_button)
+ return 0; /* OK */
+
+ if (pinentry.canceled)
+ return gpg_error (GPG_ERR_CANCELED);
+ return gpg_error (GPG_ERR_NOT_CONFIRMED);
+}
+
+
+static gpg_error_t
+cmd_message (assuan_context_t ctx, char *line)
+{
+ (void)line;
+
+ return cmd_confirm (ctx, "--one-button");
+}
+
+
+/* Return a staically allocated string with information on the mode,
+ * uid, and gid of DEVICE. On error "?" is returned if DEVICE is
+ * NULL, "-" is returned. */
+static const char *
+device_stat_string (const char *device)
+{
+#ifdef HAVE_STAT
+ static char buf[40];
+ struct stat st;
+
+ if (!device || !*device)
+ return "-";
+
+ if (stat (device, &st))
+ return "?"; /* Error */
+ snprintf (buf, sizeof buf, "%lo/%lu/%lu",
+ (unsigned long)st.st_mode,
+ (unsigned long)st.st_uid,
+ (unsigned long)st.st_gid);
+ return buf;
+#else
+ return "-";
+#endif
+}
+
+
+/* GETINFO <what>
+
+ Multipurpose function to return a variety of information.
+ Supported values for WHAT are:
+
+ version - Return the version of the program.
+ pid - Return the process id of the server.
+ flavor - Return information about the used pinentry flavor
+ ttyinfo - Return DISPLAY, ttyinfo and an emacs pinentry status
+ */
+static gpg_error_t
+cmd_getinfo (assuan_context_t ctx, char *line)
+{
+ int rc;
+ const char *s;
+ char buffer[150];
+
+ if (!strcmp (line, "version"))
+ {
+ s = VERSION;
+ rc = assuan_send_data (ctx, s, strlen (s));
+ }
+ else if (!strcmp (line, "pid"))
+ {
+
+ snprintf (buffer, sizeof buffer, "%lu", (unsigned long)getpid ());
+ rc = assuan_send_data (ctx, buffer, strlen (buffer));
+ }
+ else if (!strcmp (line, "flavor"))
+ {
+ if (!strncmp (this_pgmname, "pinentry-", 9) && this_pgmname[9])
+ s = this_pgmname + 9;
+ else
+ s = this_pgmname;
+
+ snprintf (buffer, sizeof buffer, "%s%s%s",
+ s,
+ flavor_flag? ":":"",
+ flavor_flag? flavor_flag : "");
+ rc = assuan_send_data (ctx, buffer, strlen (buffer));
+ /* if (!rc) */
+ /* rc = assuan_write_status (ctx, "FEATURES", "tabbing foo bar"); */
+ }
+ else if (!strcmp (line, "ttyinfo"))
+ {
+ char emacs_status[10];
+#ifdef INSIDE_EMACS
+ snprintf (emacs_status, sizeof emacs_status,
+ "%d", pinentry_emacs_status ());
+#else
+ strcpy (emacs_status, "-");
+#endif
+ snprintf (buffer, sizeof buffer, "%s %s %s %s %lu/%lu %s",
+ pinentry.ttyname? pinentry.ttyname : "-",
+ pinentry.ttytype_l? pinentry.ttytype_l : "-",
+ pinentry.display? pinentry.display : "-",
+ device_stat_string (pinentry.ttyname),
+#ifdef HAVE_DOSISH_SYSTEM
+ 0l, 0l,
+#else
+ (unsigned long)geteuid (), (unsigned long)getegid (),
+#endif
+ emacs_status
+ );
+ rc = assuan_send_data (ctx, buffer, strlen (buffer));
+ }
+ else
+ rc = gpg_error (GPG_ERR_ASS_PARAMETER);
+ return rc;
+}
+
+/* CLEARPASSPHRASE <cacheid>
+
+ Clear the cache passphrase associated with the key identified by
+ cacheid.
+ */
+static gpg_error_t
+cmd_clear_passphrase (assuan_context_t ctx, char *line)
+{
+ (void)ctx;
+
+ if (! line)
+ return gpg_error (GPG_ERR_ASS_INV_VALUE);
+
+ /* Remove leading and trailing white space. */
+ while (*line == ' ')
+ line ++;
+ while (line[strlen (line) - 1] == ' ')
+ line[strlen (line) - 1] = 0;
+
+ switch (password_cache_clear (line))
+ {
+ case 1: return 0;
+ case 0: return gpg_error (GPG_ERR_ASS_INV_VALUE);
+ default: return gpg_error (GPG_ERR_ASS_GENERAL);
+ }
+}
+
+/* Tell the assuan library about our commands. */
+static gpg_error_t
+register_commands (assuan_context_t ctx)
+{
+ static struct
+ {
+ const char *name;
+ gpg_error_t (*handler) (assuan_context_t, char *line);
+ } table[] =
+ {
+ { "SETDESC", cmd_setdesc },
+ { "SETPROMPT", cmd_setprompt },
+ { "SETKEYINFO", cmd_setkeyinfo },
+ { "SETREPEAT", cmd_setrepeat },
+ { "SETREPEATERROR", cmd_setrepeaterror },
+ { "SETERROR", cmd_seterror },
+ { "SETOK", cmd_setok },
+ { "SETNOTOK", cmd_setnotok },
+ { "SETCANCEL", cmd_setcancel },
+ { "GETPIN", cmd_getpin },
+ { "CONFIRM", cmd_confirm },
+ { "MESSAGE", cmd_message },
+ { "SETQUALITYBAR", cmd_setqualitybar },
+ { "SETQUALITYBAR_TT", cmd_setqualitybar_tt },
+ { "SETGENPIN", cmd_setgenpin_label },
+ { "SETGENPIN_TT", cmd_setgenpin_tt },
+ { "GETINFO", cmd_getinfo },
+ { "SETTITLE", cmd_settitle },
+ { "SETTIMEOUT", cmd_settimeout },
+ { "CLEARPASSPHRASE", cmd_clear_passphrase },
+ { NULL }
+ };
+ int i, j;
+ gpg_error_t rc;
+
+ for (i = j = 0; table[i].name; i++)
+ {
+ rc = assuan_register_command (ctx, table[i].name, table[i].handler, NULL);
+ if (rc)
+ return rc;
+ }
+ return 0;
+}
+
+
+int
+pinentry_loop2 (int infd, int outfd)
+{
+ gpg_error_t rc;
+ assuan_fd_t filedes[2];
+ assuan_context_t ctx;
+
+ /* Extra check to make sure we have dropped privs. */
+#ifndef HAVE_DOSISH_SYSTEM
+ if (getuid() != geteuid())
+ abort ();
+#endif
+
+ rc = assuan_new (&ctx);
+ if (rc)
+ {
+ fprintf (stderr, "server context creation failed: %s\n",
+ gpg_strerror (rc));
+ return -1;
+ }
+
+ /* For now we use a simple pipe based server so that we can work
+ from scripts. We will later add options to run as a daemon and
+ wait for requests on a Unix domain socket. */
+ filedes[0] = assuan_fdopen (infd);
+ filedes[1] = assuan_fdopen (outfd);
+ rc = assuan_init_pipe_server (ctx, filedes);
+ if (rc)
+ {
+ fprintf (stderr, "%s: failed to initialize the server: %s\n",
+ this_pgmname, gpg_strerror (rc));
+ return -1;
+ }
+ rc = register_commands (ctx);
+ if (rc)
+ {
+ fprintf (stderr, "%s: failed to the register commands with Assuan: %s\n",
+ this_pgmname, gpg_strerror (rc));
+ return -1;
+ }
+
+ assuan_register_option_handler (ctx, option_handler);
+#if 0
+ assuan_set_log_stream (ctx, stderr);
+#endif
+ assuan_register_reset_notify (ctx, pinentry_assuan_reset_handler);
+
+ for (;;)
+ {
+ rc = assuan_accept (ctx);
+ if (rc == -1)
+ break;
+ else if (rc)
+ {
+ fprintf (stderr, "%s: Assuan accept problem: %s\n",
+ this_pgmname, gpg_strerror (rc));
+ break;
+ }
+
+ rc = assuan_process (ctx);
+ if (rc)
+ {
+ fprintf (stderr, "%s: Assuan processing failed: %s\n",
+ this_pgmname, gpg_strerror (rc));
+ continue;
+ }
+ }
+
+ assuan_release (ctx);
+ return 0;
+}
+
+
+/* Start the pinentry event loop. The program will start to process
+ Assuan commands until it is finished or an error occurs. If an
+ error occurs, -1 is returned. Otherwise, 0 is returned. */
+int
+pinentry_loop (void)
+{
+ return pinentry_loop2 (STDIN_FILENO, STDOUT_FILENO);
+}
diff --git a/debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/pinentry.h b/debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/pinentry.h
new file mode 100644
index 00000000..b97f069b
--- /dev/null
+++ b/debian/pinentry-tqt/pinentry-tqt-1.2.1/pinentry/pinentry.h
@@ -0,0 +1,364 @@
+/* pinentry.h - The interface for the PIN entry support library.
+ * Copyright (C) 2002, 2003, 2010, 2015, 2021 g10 Code GmbH
+ *
+ * This file is part of PINENTRY.
+ *
+ * PINENTRY 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.
+ *
+ * PINENTRY 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/>.
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef PINENTRY_H
+#define PINENTRY_H
+
+#ifdef __cplusplus
+extern "C" {
+#if 0
+}
+#endif
+#endif
+
+typedef enum {
+ PINENTRY_COLOR_NONE, PINENTRY_COLOR_DEFAULT,
+ PINENTRY_COLOR_BLACK, PINENTRY_COLOR_RED,
+ PINENTRY_COLOR_GREEN, PINENTRY_COLOR_YELLOW,
+ PINENTRY_COLOR_BLUE, PINENTRY_COLOR_MAGENTA,
+ PINENTRY_COLOR_CYAN, PINENTRY_COLOR_WHITE
+} pinentry_color_t;
+
+struct pinentry
+{
+ /* The window title, or NULL. (Assuan: "SETTITLE TITLE".) */
+ char *title;
+ /* The description to display, or NULL. (Assuan: "SETDESC
+ DESC".) */
+ char *description;
+ /* The error message to display, or NULL. (Assuan: "SETERROR
+ MESSAGE".) */
+ char *error;
+ /* The prompt to display, or NULL. (Assuan: "SETPROMPT
+ prompt".) */
+ char *prompt;
+ /* The OK button text to display, or NULL. (Assuan: "SETOK
+ OK".) */
+ char *ok;
+ /* The Not-OK button text to display, or NULL. This is the text for
+ the alternative option shown by the third button. (Assuan:
+ "SETNOTOK NOTOK".) */
+ char *notok;
+ /* The Cancel button text to display, or NULL. (Assuan: "SETCANCEL
+ CANCEL".) */
+ char *cancel;
+
+ /* The buffer to store the secret into. */
+ char *pin;
+ /* The length of the buffer. */
+ int pin_len;
+ /* Whether the pin was read from an external cache (1) or entered by
+ the user (0). */
+ int pin_from_cache;
+
+ /* The name of the X display to use if X is available and supported.
+ (Assuan: "OPTION display DISPLAY".) */
+ char *display;
+ /* The name of the terminal node to open if X not available or
+ supported. (Assuan: "OPTION ttyname TTYNAME".) */
+ char *ttyname;
+ /* The type of the terminal. (Assuan: "OPTION ttytype TTYTYPE".) */
+ char *ttytype_l;
+ /* Set the alert mode (none, beep or flash). */
+ char *ttyalert;
+ /* The LC_CTYPE value for the terminal. (Assuan: "OPTION lc-ctype
+ LC_CTYPE".) */
+ char *lc_ctype;
+ /* The LC_MESSAGES value for the terminal. (Assuan: "OPTION
+ lc-messages LC_MESSAGES".) */
+ char *lc_messages;
+
+ /* True if debug mode is requested. */
+ int debug;
+
+ /* The number of seconds before giving up while waiting for user input. */
+ int timeout;
+
+ /* True if caller should grab the keyboard. (Assuan: "OPTION grab"
+ or "OPTION no-grab".) */
+ int grab;
+
+ /* The PID of the owner or 0 if not known. The owner is the process
+ * which actually triggered the the pinentry. For example gpg. */
+ unsigned long owner_pid;
+
+ /* The numeric uid (user ID) of the owner process or -1 if not
+ * known. */
+ int owner_uid;
+
+ /* The malloced hostname of the owner or NULL. */
+ char *owner_host;
+
+ /* The window ID of the parent window over which the pinentry window
+ should be displayed. (Assuan: "OPTION parent-wid WID".) */
+ int parent_wid;
+
+ /* The name of an optional file which will be touched after a curses
+ entry has been displayed. (Assuan: "OPTION touch-file
+ FILENAME".) */
+ char *touch_file;
+
+ /* The frontend should set this to -1 if the user canceled the
+ request, and to the length of the PIN stored in pin
+ otherwise. */
+ int result;
+
+ /* The frontend should set this if the NOTOK button was pressed. */
+ int canceled;
+
+ /* The frontend should set this to true if an error with the local
+ conversion occurred. */
+ int locale_err;
+
+ /* The frontend should set this to a gpg-error so that commands are
+ able to return specific error codes. This is an ugly hack due to
+ the fact that pinentry_cmd_handler_t returns the length of the
+ passphrase or a negative error code. */
+ int specific_err;
+
+ /* The frontend may store a string with the error location here. */
+ const char *specific_err_loc;
+
+ /* The frontend may store a malloced string here to emit an ERROR
+ * status code with this extra info along with SPECIFIC_ERR. */
+ char *specific_err_info;
+
+ /* The frontend should set this to true if the window close button
+ has been used. This flag is used in addition to a regular return
+ value. */
+ int close_button;
+
+ /* The caller should set this to true if only one button is
+ required. This is useful for notification dialogs where only a
+ dismiss button is required. */
+ int one_button;
+
+ /* If true a second prompt for the passphrase is shown and the user
+ is expected to enter the same passphrase again. Pinentry checks
+ that both match. (Assuan: "SETREPEAT".) */
+ char *repeat_passphrase;
+
+ /* The string to show if a repeated passphrase does not match.
+ (Assuan: "SETREPEATERROR ERROR".) */
+ char *repeat_error_string;
+
+ /* Set to true if the passphrase has been entered a second time and
+ matches the first passphrase. */
+ int repeat_okay;
+
+ /* If this is not NULL, a passphrase quality indicator is shown.
+ There will also be an inquiry back to the caller to get an
+ indication of the quality for the passphrase entered so far. The
+ string is used as a label for the quality bar. (Assuan:
+ "SETQUALITYBAR LABEL".) */
+ char *quality_bar;
+
+ /* The tooltip to be shown for the qualitybar. Malloced or NULL.
+ (Assuan: "SETQUALITYBAR_TT TOOLTIP".) */
+ char *quality_bar_tt;
+
+ /* If this is not NULL, a generate action should be shown.
+ There will be an inquiry back to the caller to get such a
+ PIN. generate action. Malloced or NULL.
+ (Assuan: "SETGENPIN LABEL" .) */
+ char *genpin_label;
+
+ /* The tooltip to be shown for the generate action. Malloced or NULL.
+ (Assuan: "SETGENPIN_TT TOOLTIP".) */
+ char *genpin_tt;
+
+ /* Specifies whether passphrase formatting should be enabled.
+ (Assuan: "OPTION formatted-passphrase") */
+ int formatted_passphrase;
+
+ /* A hint to be shown near the passphrase input field if passphrase
+ formatting is enabled. Malloced or NULL.
+ (Assuan: "OPTION formatted-passphrase-hint=HINT".) */
+ char *formatted_passphrase_hint;
+
+ /* For the curses pinentry, the color of error messages. */
+ pinentry_color_t color_fg;
+ int color_fg_bright;
+ pinentry_color_t color_bg;
+ pinentry_color_t color_so;
+ int color_so_bright;
+
+ /* Malloced and i18ned default strings or NULL. These strings may
+ include an underscore character to indicate an accelerator key.
+ A double underscore represents a plain one. */
+ /* (Assuan: "OPTION default-ok OK"). */
+ char *default_ok;
+ /* (Assuan: "OPTION default-cancel CANCEL"). */
+ char *default_cancel;
+ /* (Assuan: "OPTION default-prompt PROMPT"). */
+ char *default_prompt;
+ /* (Assuan: "OPTION default-pwmngr
+ SAVE_PASSWORD_WITH_PASSWORD_MANAGER?"). */
+ char *default_pwmngr;
+ /* (Assuan: "OPTION default-cf-visi
+ Do you really want to make your passphrase visible?"). */
+ char *default_cf_visi;
+ /* (Assuan: "OPTION default-tt-visi
+ Make passphrase visible?"). */
+ char *default_tt_visi;
+ /* (Assuan: "OPTION default-tt-hide
+ Hide passphrase"). */
+ char *default_tt_hide;
+ /* (Assuan: "OPTION default-capshint
+ Caps Lock is on"). */
+ char *default_capshint;
+
+ /* Whether we are allowed to read the password from an external
+ cache. (Assuan: "OPTION allow-external-password-cache") */
+ int allow_external_password_cache;
+
+ /* We only try the cache once. */
+ int tried_password_cache;
+
+ /* A stable identifier for the key. (Assuan: "SETKEYINFO
+ KEYINFO".) */
+ char *keyinfo;
+
+ /* Whether we may cache the password (according to the user). */
+ int may_cache_password;
+
+ /* NOTE: If you add any additional fields to this structure, be sure
+ to update the initializer in pinentry/pinentry.c!!! */
+
+ /* For the quality indicator and genpin we need to do an inquiry.
+ Thus we need to save the assuan ctx. */
+ void *ctx_assuan;
+
+ /* An UTF-8 string with an invisible character used to override the
+ default in some pinentries. Only the first character is
+ used. */
+ char *invisible_char;
+
+ /* Whether the passphrase constraints are enforced by gpg-agent.
+ (Assuan: "OPTION constraints-enforce") */
+ int constraints_enforce;
+
+ /* A short translated hint for the user with the constraints for new
+ passphrases to be displayed near the passphrase input field.
+ Malloced or NULL.
+ (Assuan: "OPTION constraints-hint-short=At least 8 characters".) */
+ char *constraints_hint_short;
+
+ /* A longer translated hint for the user with the constraints for new
+ passphrases to be displayed for example as tooltip. Malloced or NULL.
+ (Assuan: "OPTION constraints-hint-long=The passphrase must ...".) */
+ char *constraints_hint_long;
+
+ /* A short translated title for an error dialog informing the user about
+ unsatisfied passphrase constraints. Malloced or NULL.
+ (Assuan: "OPTION constraints-error-title=Passphrase Not Allowed".) */
+ char *constraints_error_title;
+
+};
+typedef struct pinentry *pinentry_t;
+
+
+/* The pinentry command handler type processes the pinentry request
+ PIN. If PIN->pin is zero, request a confirmation, otherwise a PIN
+ entry. On confirmation, the function should return TRUE if
+ confirmed, and FALSE otherwise. On PIN entry, the function should
+ return -1 if an error occurred or the user cancelled the operation
+ and 1 otherwise. */
+typedef int (*pinentry_cmd_handler_t) (pinentry_t pin);
+
+/* Start the pinentry event loop. The program will start to process
+ Assuan commands until it is finished or an error occurs. If an
+ error occurs, -1 is returned and errno indicates the type of an
+ error. Otherwise, 0 is returned. */
+int pinentry_loop (void);
+
+/* The same as above but allows to specify the i/o descriptors.
+ * infd and outfd will be duplicated in this function so the caller
+ * still has to close them if necessary.
+ */
+int pinentry_loop2 (int infd, int outfd);
+
+const char *pinentry_get_pgmname (void);
+
+char *pinentry_get_title (pinentry_t pe);
+
+/* Run a quality inquiry for PASSPHRASE of LENGTH. */
+int pinentry_inq_quality (pinentry_t pin,
+ const char *passphrase, size_t length);
+
+/* Run a checkpin inquiry for PASSPHRASE of LENGTH. Returns NULL, if the
+ passphrase satisfies the constraints. Otherwise, returns a malloced error
+ string. */
+char *pinentry_inq_checkpin (pinentry_t pin,
+ const char *passphrase, size_t length);
+
+/* Run a genpin iquriry. Returns a malloced string or NULL */
+char *pinentry_inq_genpin (pinentry_t pin);
+
+/* Try to make room for at least LEN bytes for the pin in the pinentry
+ PIN. Returns new buffer on success and 0 on failure. */
+char *pinentry_setbufferlen (pinentry_t pin, int len);
+
+/* Use the buffer at BUFFER for PIN->PIN. BUFFER must be NULL or
+ allocated using secmem_alloc. LEN is the size of the buffer. If
+ it is unknown, but BUFFER is a NUL terminated string, you pass 0 to
+ just use strlen(buffer)+1. */
+void pinentry_setbuffer_use (pinentry_t pin, char *buffer, int len);
+
+/* Initialize the secure memory subsystem, drop privileges and
+ return. Must be called early. */
+void pinentry_init (const char *pgmname);
+
+/* Return true if either DISPLAY is set or ARGV contains the string
+ "--display". */
+int pinentry_have_display (int argc, char **argv);
+
+/* Parse the command line options. May exit the program if only help
+ or version output is requested. */
+void pinentry_parse_opts (int argc, char *argv[]);
+
+/* Set the optional flag used with getinfo. */
+void pinentry_set_flavor_flag (const char *string);
+
+
+
+/* The caller must define this variable to process assuan commands. */
+extern pinentry_cmd_handler_t pinentry_cmd_handler;
+
+
+
+
+
+#ifdef HAVE_W32_SYSTEM
+/* Windows declares sleep as obsolete, but provides a definition for
+ _sleep but non for the still existing sleep. */
+#define sleep(a) _sleep ((a))
+#endif /*HAVE_W32_SYSTEM*/
+
+
+
+#if 0
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PINENTRY_H */