From e3b1e3857e00c6e8216e953b0b38f4dcda00cd53 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 31 Aug 2022 14:18:24 +0900 Subject: Drop WindowsCE support. * contrib/*: Remove. * Makefile.am (EXTRA_DIST): Don't include contrib/. * configure.ac (HAVE_W32CE_SYSTEM): Remove. * src/gpgcedev.c: Remove. * src/gpgcedev.def: Remove. * src/gpgcemgr.c: Remove. * src/system-w32ce.c: Remove. * src/w32ce-add.h: Remove. * src/w32ce-fd-t.inc.h: Remove. * src/Makefile.am (EXTRA_DIST, parts_of_assuan_h, common_sources): Fix. * src/assuan-buffer.c [HAVE_W32CE_SYSTEM]: No conditionalize. * src/setenv.c [HAVE_W32CE_SYSTEM]: Likewise. * src/assuan-defs.h [HAVE_W32CE_SYSTEM]: Remove dependent part. * src/assuan-error.c [HAVE_W32CE_SYSTEM]: Likewise. * src/assuan-handler.c [HAVE_W32CE_SYSTEM]: Likewise. * src/assuan-socket.c [HAVE_W32CE_SYSTEM]: Likewise. * src/system.c [HAVE_W32CE_SYSTEM]: Likewise. * src/sysutils.c [HAVE_W32CE_SYSTEM]: Likewise. * tests/Makefile.am (EXTRA_DIST): Fix. (w32cetools): Remove. * tests/common.h [HAVE_W32CE_SYSTEM]: Remove dependent part. * tests/pipeconnect.c [HAVE_W32CE_SYSTEM]: Likewise. * tests/ce-createpipe.c: Remove. * tests/ce-server.c: Remove. -- GnuPG-bug-id: 6170 Signed-off-by: NIIBE Yutaka --- Makefile.am | 2 +- NEWS | 2 + configure.ac | 21 +- contrib/ChangeLog-2011 | 29 - contrib/conf-w32ce-msc/build.mk | 169 ---- contrib/conf-w32ce-msc/config.h | 188 ----- contrib/conf-w32ce-msc/stdint.h | 9 - src/Makefile.am | 29 +- src/assuan-buffer.c | 2 - src/assuan-defs.h | 9 - src/assuan-error.c | 5 - src/assuan-handler.c | 24 +- src/assuan-socket.c | 2 - src/gpgcedev.c | 1640 --------------------------------------- src/gpgcedev.def | 34 - src/gpgcemgr.c | 608 --------------- src/setenv.c | 4 - src/system-w32ce.c | 706 ----------------- src/system.c | 4 - src/sysutils.c | 87 --- src/w32ce-add.h | 34 - src/w32ce-fd-t.inc.h | 33 - tests/Makefile.am | 6 +- tests/ce-createpipe.c | 179 ----- tests/ce-server.c | 1418 --------------------------------- tests/common.h | 5 - tests/pipeconnect.c | 50 -- 27 files changed, 11 insertions(+), 5288 deletions(-) delete mode 100644 contrib/ChangeLog-2011 delete mode 100755 contrib/conf-w32ce-msc/build.mk delete mode 100644 contrib/conf-w32ce-msc/config.h delete mode 100755 contrib/conf-w32ce-msc/stdint.h delete mode 100644 src/gpgcedev.c delete mode 100644 src/gpgcedev.def delete mode 100644 src/gpgcemgr.c delete mode 100644 src/system-w32ce.c delete mode 100644 src/w32ce-add.h delete mode 100644 src/w32ce-fd-t.inc.h delete mode 100644 tests/ce-createpipe.c delete mode 100644 tests/ce-server.c diff --git a/Makefile.am b/Makefile.am index 11e4696..0da00ea 100644 --- a/Makefile.am +++ b/Makefile.am @@ -27,7 +27,7 @@ GITLOG_TO_CHANGELOG=gitlog-to-changelog EXTRA_DIST = autogen.sh autogen.rc README.GIT VERSION \ ChangeLog-2011 doc/ChangeLog-2011 src/ChangeLog-2011 \ - tests/ChangeLog-2011 contrib/ChangeLog-2011 \ + tests/ChangeLog-2011 \ build-aux/git-log-footer build-aux/git-log-fix if BUILD_DOC diff --git a/NEWS b/NEWS index 0ed6e87..dc04e8f 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,8 @@ Noteworthy changes in version 2.5.6 (unreleased) [C8/A8/R_] * Use of ASSUAN_SYSTEM_NPTH is deprecated. Instead, please use the gpgrt_set_syscall_clamp function from gpgrt library. + * No support for WindowsCE, any more. + Noteworthy changes in version 2.5.5 (2021-03-22) [C8/A8/R5] ------------------------------------------------ diff --git a/configure.ac b/configure.ac index 29c66dd..b5c2cc7 100644 --- a/configure.ac +++ b/configure.ac @@ -156,9 +156,6 @@ AH_TOP([ #ifndef _ASSUAN_CONFIG_H_INCLUDED #define _ASSUAN_CONFIG_H_INCLUDED -/* Enable gpg-error's strerror macro under W32CE. */ -#define GPG_ERR_ENABLE_ERRNO_MACROS 1 - /* Provide the es_ macro for estream. */ #define GPGRT_ENABLE_ES_MACROS 1 @@ -213,7 +210,6 @@ fi have_dosish_system=no have_w32_system=no have_w64_system=no -have_w32ce_system=no case "${host}" in *-linux*) if test "$GCC" = yes; then @@ -225,11 +221,6 @@ case "${host}" in have_w32_system=yes have_w64_system=yes ;; - *-mingw32ce*) - have_dosish_system=yes - have_w32_system=yes - have_w32ce_system=yes - ;; *-mingw32*) have_dosish_system=yes have_w32_system=yes @@ -254,13 +245,9 @@ if test "$have_w32_system" = yes; then AC_DEFINE(HAVE_W64_SYSTEM,1, [Defined if we run on a 64 bit W32 API based system]) fi - if test "$have_w32ce_system" = yes; then - AC_DEFINE(HAVE_W32CE_SYSTEM,1,[Defined if we run on WindowsCE]) - fi AC_CHECK_HEADERS([winsock2.h]) fi AM_CONDITIONAL(HAVE_W32_SYSTEM, test "$have_w32_system" = yes) -AM_CONDITIONAL(HAVE_W32CE_SYSTEM, test "$have_w32ce_system" = yes) AM_CONDITIONAL(HAVE_W64_SYSTEM, test "$have_w64_system" = yes) @@ -302,12 +289,8 @@ AC_CHECK_FUNC(setsockopt, , AC_CHECK_LIB(socket, setsockopt, AC_SUBST(NETLIBS) if test "$have_w32_system" = yes; then - if test "$have_w32ce_system" = yes; then - NETLIBS="-lws2 $NETLIBS" - else - # FIXME: Check why we need to use ws2_32 and document that. - NETLIBS="-lws2_32 $NETLIBS" - fi + # FIXME: Check why we need to use ws2_32 and document that. + NETLIBS="-lws2_32 $NETLIBS" fi # diff --git a/contrib/ChangeLog-2011 b/contrib/ChangeLog-2011 deleted file mode 100644 index 65306e3..0000000 --- a/contrib/ChangeLog-2011 +++ /dev/null @@ -1,29 +0,0 @@ -2011-12-01 Werner Koch - - NB: ChangeLog files are no longer manually maintained. Starting - on December 1st, 2011 we put change information only in the GIT - commit log, and generate a top-level ChangeLog file from logs at - "make dist". See doc/HACKING for details. - -2010-11-15 Marcus Brinkmann - - * conf-w32ce-msc/stdint.h: New file. - * conf-w32ce-msc/build.mk (conf_sources): Add stdint.h. - (copy-static-source): Revert last change. - -2010-11-15 Werner Koch - - * conf-w32ce-msc/config.h (strdup, strcasecmp): Add macros. - - * conf-w32ce-msc/build.mk (copy-static-source): Create stdint.h. - (all): Add ws2.lib - (clean): New. - -2010-11-02 Werner Koch - - * conf-w32ce-msc/build.mk: Change directory layout. - -2010-11-01 Werner Koch - - * conf-w32ce-msc/build.mk: New. - * conf-w32ce-msc/config.h: New. diff --git a/contrib/conf-w32ce-msc/build.mk b/contrib/conf-w32ce-msc/build.mk deleted file mode 100755 index 70b9634..0000000 --- a/contrib/conf-w32ce-msc/build.mk +++ /dev/null @@ -1,169 +0,0 @@ -# build.mk - Makefile to build libgpg-error using Visual-C -# Copyright 2010 g10 Code GmbH -# -# This file is free software; as a special exception the author gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. -# -# This file 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. - -# This is a helper make script to build libgpg-error for WindowsCE -# using the Microsoft Visual C compiler. - -# The target build directory where we run the Visual C compiler/ This -# needs to be an absolute directory name. Further we expect this -# structure of the tree: -# -# TARGET/src - Source directories: One directory for each project -# /bin - Installed DLLs -# /lib - Installed import libs. -# /include - Instaled header files. - -targetdir = /home/smb/xppro-gnu -targetsrc = $(targetdir)/src - -# Install directories (relative) -bindir = ../../../bin -libdir = ../../../lib -incdir = ../../../include - -help: - @echo "Run " - @echo " make -f ../contrib/conf-w32ce-msc/build.mk copy-source" - @echo "on the POSIX system and then" - @echo " nmake -f build.mk all" - @echo " nmake -f build.mk install" - @echo "on the Windows system" - -ce_defines = -DWINCE -D_WIN32_WCE=0x502 -DUNDER_CE \ - -DWIN32_PLATFORM_PSPC -D_UNICODE -DUNICODE \ - -D_CONSOLE -DARM -D_ARM_ -#-D_DEBUG -DDEBUG - -# See libgpg-error's build-mk for a list of compiler options. -CFLAGS = -nologo -W3 -fp:fast -Os $(ce_defines) \ - -DHAVE_CONFIG_H -DDLL_EXPORT -D_CRT_SECURE_NO_WARNINGS \ - -I. -I$(incdir) -I$(incdir)/gpg-extra - -LDFLAGS = - -# Standard source files -sources = \ - assuan.c \ - context.c \ - system.c \ - debug.c \ - conversion.c \ - sysutils.c \ - client.c \ - server.c \ - assuan-error.c \ - assuan-buffer.c \ - assuan-handler.c \ - assuan-inquire.c \ - assuan-listen.c \ - assuan-pipe-server.c \ - assuan-socket-server.c \ - assuan-pipe-connect.c \ - assuan-socket-connect.c \ - assuan-uds.c \ - assuan-logging.c \ - assuan-socket.c \ - system-w32ce.c \ - assuan-io.c \ - putc_unlocked.c \ - memrchr.c \ - stpcpy.c \ - setenv.c \ - vasprintf.c \ - assuan-defs.h \ - debug.h \ - libassuan.def - -# The object files we need to create from sources. -objs = \ - assuan.obj \ - context.obj \ - system.obj \ - debug.obj \ - conversion.obj \ - sysutils.obj \ - client.obj \ - server.obj \ - assuan-error.obj \ - assuan-buffer.obj \ - assuan-handler.obj \ - assuan-inquire.obj \ - assuan-listen.obj \ - assuan-pipe-server.obj \ - assuan-socket-server.obj \ - assuan-pipe-connect.obj \ - assuan-socket-connect.obj \ - assuan-uds.obj \ - assuan-logging.obj \ - assuan-socket.obj \ - system-w32ce.obj \ - assuan-io.obj \ - putc_unlocked.obj \ - memrchr.obj \ - stpcpy.obj \ - setenv.obj \ - vasprintf.obj - - -# Sources files in this directory inclduing this Makefile -conf_sources = \ - build.mk \ - config.h \ - stdint.h - -# Source files built by running the standard build system. -built_sources = \ - assuan.h - - -copy-static-source: - @if [ ! -f ./assuan-defs.h ]; then \ - echo "Please cd to the src/ directory first"; \ - exit 1; \ - fi - cp -t $(targetsrc)/libassuan/src $(sources); - cd ../contrib/conf-w32ce-msc ; \ - cp -t $(targetsrc)/libassuan/src $(conf_sources) - - -copy-built-source: - @if [ ! -f ./assuan.h ]; then \ - echo "Please build using ./autogen.sh --build-w32ce first"; \ - exit 1; \ - fi - cp -t $(targetsrc)/libassuan/src $(built_sources) - -copy-source: copy-static-source copy-built-source - - -.c.obj: - $(CC) $(CFLAGS) -c $< - -all: $(sources) $(conf_sources) $(built_sources) $(objs) - link /DLL /IMPLIB:libassuan-0-msc.lib \ - /OUT:libassuan-0-msc.dll \ - /DEF:libassuan.def /NOLOGO /MANIFEST:NO \ - /NODEFAULTLIB:"oldnames.lib" /DYNAMICBASE:NO \ - $(objs) $(libdir)/libgpg-error-0-msc.lib \ - coredll.lib corelibc.lib ole32.lib oleaut32.lib uuid.lib \ - commctrl.lib ws2.lib /subsystem:windowsce,5.02 - -# Note that we don't need to create the install directories because -# libgpg-error must have been build and installed prior to this -# package. -install: all - copy /y libassuan-0-msc.dll $(bindir:/=\) - copy /y libassuan-0-msc.lib $(libdir:/=\) - copy /y assuan.h $(incdir:/=\) - -clean: - del *.obj libassuan-0-msc.lib libassuan-0-msc.dll libassuan-0-msc.exp - diff --git a/contrib/conf-w32ce-msc/config.h b/contrib/conf-w32ce-msc/config.h deleted file mode 100644 index c247377..0000000 --- a/contrib/conf-w32ce-msc/config.h +++ /dev/null @@ -1,188 +0,0 @@ -/* config.h for building with Visual-C for WindowsCE. - * Copyright 2010 g10 Code GmbH - * - * This file is free software; as a special exception the author gives - * unlimited permission to copy and/or distribute it, with or without - * modifications, as long as this notice is preserved. - * - * This file 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. - */ - -/* This file was originally created by running - * ./autogen.sh --build-w32ce - * on svn revision 389 (libassuan 2.0.2-svn389) and then adjusted to work - * with Visual-C. - */ - -#ifndef _ASSUAN_CONFIG_H_INCLUDED -#define _ASSUAN_CONFIG_H_INCLUDED - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "2.0.2-svn389-msc1" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "libassuan " PACKAGE_VERSION - -/* Name of this package */ -#define PACKAGE "libassuan" - -/* Bug report address */ -#define PACKAGE_BUGREPORT "bug-libassuan@gnupg.org" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "libassuan" - - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "libassuan" - -/* Define to the home page for this package. */ -#define PACKAGE_URL "" - -/* Version of this package */ -#define VERSION PACKAGE_VERSION - - -/* Enable gpg-error's strerror macro under W32CE. */ -#define GPG_ERR_ENABLE_ERRNO_MACROS 1 - - -/* Define to 1 if you have the declaration of `sys_siglist', and to 0 if you - don't. */ -#define HAVE_DECL_SYS_SIGLIST 0 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_DLFCN_H */ - -/* Defined if we run on some of the PCDOS like systems (DOS, Windoze. OS/2) - with special properties like no file modes */ -#define HAVE_DOSISH_SYSTEM 1 - -/* Define to 1 if you have the `flockfile' function. */ -/* #undef HAVE_FLOCKFILE */ - -/* Define to 1 if you have the `fopencookie' function. */ -/* #undef HAVE_FOPENCOOKIE */ - -/* Define to 1 if you have the `funlockfile' function. */ -/* #undef HAVE_FUNLOCKFILE */ - -/* Define to 1 if you have the `funopen' function. */ -/* #undef HAVE_FUNOPEN */ - -/* Define to 1 if you have the `inet_pton' function. */ -/* #undef HAVE_INET_PTON */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_INTTYPES_H */ - -/* Define to 1 if you have the `isascii' function. */ -#define HAVE_ISASCII 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_LOCALE_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the `memrchr' function. */ -/* #undef HAVE_MEMRCHR */ - -/* Define to 1 if you have the `nanosleep' function in libc. */ -/* #undef HAVE_NANOSLEEP */ - -/* Define to 1 if you have the `putc_unlocked' function. */ -/* #undef HAVE_PUTC_UNLOCKED */ - -/* Define to 1 if you have the `setenv' function. */ -/* #undef HAVE_SETENV */ - -/* Defined if SO_PEERCRED is supported (Linux specific) */ -/* #undef HAVE_SO_PEERCRED */ - -/* Define to 1 if you have the header file. */ -#define HAVE_STDINT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the `stpcpy' function. */ -/* #undef HAVE_STPCPY */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_STRINGS_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_SOCKET_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_STAT_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_TYPES_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_UIO_H */ - -/* Define to 1 if the system has the type `uintptr_t'. */ -#define HAVE_UINTPTR_T 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_UNISTD_H */ - -/* Define to 1 if you have the `vasprintf' function. */ -/* #undef HAVE_VASPRINTF */ - -/* Defined if we run on WindowsCE */ -#define HAVE_W32CE_SYSTEM 1 - -/* Defined if we run on a W32 API based system */ -#define HAVE_W32_SYSTEM 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_WINSOCK2_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_WS2TCPIP_H 1 - -/* Define to 1 if your C compiler doesn't accept -c and -o together. */ -/* #undef NO_MINUS_C_MINUS_O */ - -/* Define as the return type of signal handlers (`int' or `void'). */ -#define RETSIGTYPE void - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Defined if descriptor passing is supported */ -/* #undef USE_DESCRIPTOR_PASSING */ - -/* Enable extensions on AIX 3, Interix. */ -#ifndef _ALL_SOURCE -# define _ALL_SOURCE 1 -#endif -/* Enable GNU extensions on systems that have them. */ -#ifndef _GNU_SOURCE -# define _GNU_SOURCE 1 -#endif -/* Enable threading extensions on Solaris. */ -#ifndef _POSIX_PTHREAD_SEMANTICS -# define _POSIX_PTHREAD_SEMANTICS 1 -#endif - - -/* snprintf is not part of oldnames.lib thus we redefine it here. */ -#define snprintf _snprintf - -/* We also need to define these functions. */ -#define strdup _strdup -#define strcasecmp _stricmp - - -#endif /*_ASSUAN_CONFIG_H_INCLUDED*/ - diff --git a/contrib/conf-w32ce-msc/stdint.h b/contrib/conf-w32ce-msc/stdint.h deleted file mode 100755 index 0a821b7..0000000 --- a/contrib/conf-w32ce-msc/stdint.h +++ /dev/null @@ -1,9 +0,0 @@ -typedef unsigned long long uint64_t; -typedef long long int64_t; -typedef unsigned int uint32_t; -typedef int int32_t; -typedef unsigned short uint16_t; -typedef short int16_t; -typedef unsigned int uintptr_t; -typedef int intptr_t; - diff --git a/src/Makefile.am b/src/Makefile.am index 321aea3..f3a3aac 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -23,7 +23,7 @@ pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libassuan.pc EXTRA_DIST = libassuan-config.in libassuan.m4 libassuan.vers \ - versioninfo.rc.in libassuan.def mkheader.c gpgcedev.def \ + versioninfo.rc.in libassuan.def mkheader.c \ libassuan.pc.in AM_CPPFLAGS = -I.. @@ -35,10 +35,6 @@ endif m4datadir = $(datadir)/aclocal m4data_DATA = libassuan.m4 lib_LTLIBRARIES = libassuan.la -if HAVE_W32CE_SYSTEM -lib_LTLIBRARIES += libgpgcedev.la -bin_PROGRAMS = gpgcemgr -endif nodist_include_HEADERS = assuan.h if HAVE_LD_VERSION_SCRIPT @@ -52,11 +48,10 @@ CLEANFILES = mkheader assuan.h BUILT_SOURCES = assuan.h parts_of_assuan_h = \ - posix-includes.inc.h w32-includes.inc.h \ + posix-includes.inc.h \ posix-types.inc.h w32-types.inc.h \ - posix-fd-t.inc.h w32-fd-t.inc.h w32ce-fd-t.inc.h \ - posix-sock-nonce.inc.h w32-sock-nonce.inc.h \ - w32ce-add.h + posix-fd-t.inc.h w32-fd-t.inc.h \ + posix-sock-nonce.inc.h w32-sock-nonce.inc.h common_sources = \ assuan.h.in $(parts_of_assuan_h) \ @@ -78,11 +73,7 @@ common_sources = \ assuan-socket.c if HAVE_W32_SYSTEM -if HAVE_W32CE_SYSTEM -common_sources += system-w32ce.c -else common_sources += system-w32.c -endif else common_sources += system-posix.c endif @@ -139,18 +130,6 @@ libassuan_la_DEPENDENCIES = @LTLIBOBJS@ \ $(srcdir)/libassuan.vers $(libassuan_deps) libassuan_la_LIBADD = @LTLIBOBJS@ @NETLIBS@ @GPG_ERROR_LIBS@ -if HAVE_W32CE_SYSTEM -libgpgcedev_la_SOURCES = gpgcedev.c -libgpgcedev_la_CPPFLAGS = $(AM_CPPFLAGS) -libgpgcedev_la_LDFLAGS = $(no_undefined) -export-symbols $(srcdir)/gpgcedev.def -libgpgcedev_la_DEPENDENCIES = gpgcedev.def -gpgcemgr_SOURCES = gpgcemgr.c -gpgcemgr_CPPFLAGS = $(AM_CPPFLAGS) -install-exec-hook: - mv -f $(DESTDIR)$(bindir)/libgpgcedev-0.dll \ - $(DESTDIR)$(bindir)/gpgcedev.dll -endif - mkheader$(EXEEXT_FOR_BUILD): mkheader.c Makefile $(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) $(CPPFLAGS_FOR_BUILD) \ $(LDFLAGS_FOR_BUILD) -I. -I$(srcdir) -o $@ $(srcdir)/mkheader.c diff --git a/src/assuan-buffer.c b/src/assuan-buffer.c index 7cb3032..895eb93 100644 --- a/src/assuan-buffer.c +++ b/src/assuan-buffer.c @@ -29,10 +29,8 @@ #endif #include #ifdef HAVE_W32_SYSTEM -#ifndef HAVE_W32CE_SYSTEM # include #endif -#endif #include "assuan-defs.h" diff --git a/src/assuan-defs.h b/src/assuan-defs.h index 37a50af..47ff4ef 100644 --- a/src/assuan-defs.h +++ b/src/assuan-defs.h @@ -375,15 +375,6 @@ FILE *_assuan_funopen(void *cookie, /*-- sysutils.c --*/ const char *_assuan_sysutils_blurb (void); -#ifdef HAVE_W32CE_SYSTEM - -#define getpid() GetCurrentProcessId () -char *_assuan_getenv (const char *name); -#define getenv(a) _assuan_getenv ((a)) - -#endif /*HAVE_W32CE_SYSTEM*/ - - /* Prototypes for replacement functions. */ #ifndef HAVE_MEMRCHR void *memrchr (const void *block, int c, size_t size); diff --git a/src/assuan-error.c b/src/assuan-error.c index 8799203..57fb740 100644 --- a/src/assuan-error.c +++ b/src/assuan-error.c @@ -54,14 +54,9 @@ _assuan_w32_strerror (assuan_context_t ctx, int ec) { if (ec == -1) ec = (int)GetLastError (); -#ifdef HAVE_W32CE_SYSTEM - snprintf (ctx->w32_strerror, sizeof (ctx->w32_strerror) - 1, - "ec=%d", (int)GetLastError ()); -#else FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, ec, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), ctx->w32_strerror, sizeof (ctx->w32_strerror) - 1, NULL); -#endif return ctx->w32_strerror; } #endif diff --git a/src/assuan-handler.c b/src/assuan-handler.c index a572b62..126eccb 100644 --- a/src/assuan-handler.c +++ b/src/assuan-handler.c @@ -311,16 +311,6 @@ std_handler_input (assuan_context_t ctx, char *line) if (rc) return PROCESS_DONE (ctx, rc); -#ifdef HAVE_W32CE_SYSTEM - oldfd = fd; - fd = _assuan_w32ce_finish_pipe ((int)fd, 0); - if (fd == INVALID_HANDLE_VALUE) - return PROCESS_DONE (ctx, set_error (ctx, GPG_ERR_ASS_PARAMETER, - "rvid conversion failed")); - TRACE2 (ctx, ASSUAN_LOG_SYSIO, "std_handler_input", ctx, - "turned RVID 0x%x into handle 0x%x", oldfd, fd); -#endif - if (ctx->input_notify_fnc) { oldfd = ctx->input_fd; @@ -352,16 +342,6 @@ std_handler_output (assuan_context_t ctx, char *line) if (rc) return PROCESS_DONE (ctx, rc); -#ifdef HAVE_W32CE_SYSTEM - oldfd = fd; - fd = _assuan_w32ce_finish_pipe ((int)fd, 1); - if (fd == INVALID_HANDLE_VALUE) - return PROCESS_DONE (ctx, set_error (ctx, gpg_err_code_from_syserror (), - "rvid conversion failed")); - TRACE2 (ctx, ASSUAN_LOG_SYSIO, "std_handler_output", ctx, - "turned RVID 0x%x into handle 0x%x", oldfd, fd); -#endif - if (ctx->output_notify_fnc) { oldfd = ctx->output_fd; @@ -935,9 +915,7 @@ assuan_get_active_fds (assuan_context_t ctx, int what, if (ctx->outbound.fd != ASSUAN_INVALID_FD) fdarray[n++] = ctx->outbound.fd; if (ctx->outbound.data.fp) -#if defined(HAVE_W32CE_SYSTEM) - fdarray[n++] = (void*)fileno (ctx->outbound.data.fp); -#elif defined(HAVE_W32_SYSTEM) +#if defined(HAVE_W32_SYSTEM) fdarray[n++] = (void*)_get_osfhandle (fileno (ctx->outbound.data.fp)); #else fdarray[n++] = fileno (ctx->outbound.data.fp); diff --git a/src/assuan-socket.c b/src/assuan-socket.c index 0588dc2..bb5ccfd 100644 --- a/src/assuan-socket.c +++ b/src/assuan-socket.c @@ -29,9 +29,7 @@ # define WIN32_LEAN_AND_MEAN # include # include -#ifndef HAVE_W32CE_SYSTEM # include -#endif #else # include # include diff --git a/src/gpgcedev.c b/src/gpgcedev.c deleted file mode 100644 index c841ec2..0000000 --- a/src/gpgcedev.c +++ /dev/null @@ -1,1640 +0,0 @@ -/* gpgcedrv.c - WindowsCE device driver to implement pipe and syslog. - * Copyright (C) 2010 Free Software Foundation, Inc. - * - * This file is part of Assuan. - * - * Assuan is free software; you can redistribute it and/or modify it - * under the terms of 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. - * - * Assuan 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see . - * SPDX-License-Identifier: LGPL-3.0+ - */ - -#include -#include -#include -#include -#include -#include - -/* FIXME Cancel not handled. */ - -#define DBGFILENAME "\\gpgcedev.dbg" -#define LOGFILENAME L"\\gpgcedev.log" -#define GPGCEDEV_KEY_NAME L"Drivers\\GnuPG_Device" -#define GPGCEDEV_KEY_NAME2 L"Drivers\\GnuPG_Log" - - -/* Missing IOCTLs in the current mingw32ce. */ -#ifndef IOCTL_PSL_NOTIFY -# define FILE_DEVICE_PSL 259 -# define IOCTL_PSL_NOTIFY \ - CTL_CODE (259, 255, METHOD_NEITHER, FILE_ANY_ACCESS) -#endif /*IOCTL_PSL_NOTIFY*/ - - -/* The IOCTL to return the rendezvous id of the handle. - - The required outbuf parameter is the address of a variable to store - the rendezvous ID, which is a LONG value. */ -#define GPGCEDEV_IOCTL_GET_RVID \ - CTL_CODE (FILE_DEVICE_STREAMS, 2048, METHOD_BUFFERED, FILE_ANY_ACCESS) - -/* The IOCTL used to create the pipe. - - The caller sends this IOCTL to the read or the write handle. The - required inbuf parameter is address of a variable holding the - rendezvous id of the pipe's other end. There is one possible - problem with the code: If a pipe is kept in non-rendezvous state - until after the rendezvous ids overflow, it is possible that the - wrong end will be used. However this is not a realistic scenario. */ -#define GPGCEDEV_IOCTL_MAKE_PIPE \ - CTL_CODE (FILE_DEVICE_STREAMS, 2049, METHOD_BUFFERED, FILE_ANY_ACCESS) - -/* The IOCTL used to unblock a blocking thread. - - The caller sends this IOCTL to the read or the write handle. No - parameter is required. The effect is that a reader or writer - blocked on the same handle is unblocked (and will return - ERROR_BUSY). Note that the operation can be repeated, if so - desired. The state of the pipe itself will not be affected in any - way. */ -#define GPGCEDEV_IOCTL_UNBLOCK \ - CTL_CODE (FILE_DEVICE_STREAMS, 2050, METHOD_BUFFERED, FILE_ANY_ACCESS) - -/* The IOCTL to assign a rendezvous id to a process. - - The required inbuf parameters are the rendezvous ID to assign and - the process ID of the process receiving the RVID. The handle on - which this is called is not really used at all! */ -#define GPGCEDEV_IOCTL_ASSIGN_RVID \ - CTL_CODE (FILE_DEVICE_STREAMS, 2051, METHOD_BUFFERED, FILE_ANY_ACCESS) - - -/* An object to describe a pipe. */ -struct pipeimpl_s -{ - CRITICAL_SECTION critsect; /* Lock for all members. */ - - int refcnt; - char *buffer; - size_t buffer_size; - size_t buffer_len; /* The valid length of the bufer. */ - size_t buffer_pos; /* The actual read position. */ - -#define PIPE_FLAG_NO_READER 1 -#define PIPE_FLAG_NO_WRITER 2 -#define PIPE_FLAG_UNBLOCK_READER 4 -#define PIPE_FLAG_UNBLOCK_WRITER 8 -#define PIPE_FLAG_HALT_MONITOR 16 - int flags; - - HANDLE space_available; /* Set if space is available. */ - HANDLE data_available; /* Set if data is available. */ - - /* For the monitor thread started by ASSIGN_RVID. */ - HANDLE monitor_proc; - int monitor_access; - LONG monitor_rvid; -}; -typedef struct pipeimpl_s *pipeimpl_t; - - -/* An object to describe a logging context. We can't write directly - to the log stream because we want to do line buffering and thus we - need to store data until we see LF. */ -struct logimpl_s; -typedef struct logimpl_s *logimpl_t; -struct logimpl_s -{ - unsigned long logid; /* An identifier for a log source. */ - unsigned long dsec; /* Tenth of a second since system start. */ - char *line; /* Malloced line buffer. */ - size_t linesize; /* Allocated size of LINE. */ - size_t linelen; /* Used length of the line. */ - int truncated; /* Indicates a truncated log line. */ -}; - - - -/* An object to store information pertaining to an open-context. */ -struct opnctx_s; -typedef struct opnctx_s *opnctx_t; -struct opnctx_s -{ - int inuse; /* True if this object has valid data. */ - int is_log; /* True if this describes a log device. */ - LONG rvid; /* The unique rendezvous identifier. */ - DWORD access_code;/* Value from OpenFile. */ - DWORD share_mode; /* Value from OpenFile. */ - - /* The state shared by all pipe users. Only used if IS_LOG is false. */ - pipeimpl_t pipeimpl; - - /* The state used to implement a log stream. Only used if IS_LOG is true. */ - logimpl_t logimpl; -}; - -/* A malloced table of open-context and the number of allocated slots. */ -static opnctx_t opnctx_table; -static size_t opnctx_table_size; -/* The macros make sure that 0 is never a valid openctx_arg. */ -#define OPNCTX_TO_IDX(ctx_arg) (((ctx_arg) - opnctx_table) + 1) -#define OPNCTX_FROM_IDX(idx) (&opnctx_table[(idx) - 1]) -#define OPNCTX_VALID_IDX_P(idx) ((idx) > 0 && (idx) <= opnctx_table_size) - -typedef struct monitor_s *monitor_t; -struct monitor_s -{ - int inuse; /* True if this object has valid data. */ - pipeimpl_t pipeimpl; -}; -static monitor_t monitor_table; -static size_t monitor_table_size; - -/* A criticial section object used to protect the OPNCTX_TABLE and - MONITOR_TABLE. */ -static CRITICAL_SECTION opnctx_table_cs; - - - -/* A global object to control the logging. */ -struct { - CRITICAL_SECTION lock; /* Lock for this structure. */ - HANDLE filehd; /* Handle of the log output file. */ - int references; /* Number of objects references this one. */ -} logcontrol; - - -/* We don't need a device context for the pipe thus we use the address - of the critical section object for it. */ -#define PIPECTX_VALUE ((DWORD)(&opnctx_table_cs)) - -/* The device context for the log device is the address of our - control structure. */ -#define LOGCTX_VALUE ((DWORD)(&logcontrol)) - - -/* True if we have enabled debugging. */ -static int enable_debug; - -/* True if logging has been enabled. */ -static int enable_logging; - - - -static void -log_debug (const char *fmt, ...) -{ - if (enable_debug) - { - va_list arg_ptr; - FILE *fp; - - fp = fopen (DBGFILENAME, "a+"); - if (!fp) - return; - va_start (arg_ptr, fmt); - vfprintf (fp, fmt, arg_ptr); - va_end (arg_ptr); - fclose (fp); - } -} - - -/* Return a new rendezvous id. We will never return an RVID of 0. */ -static LONG -create_rendezvous_id (void) -{ - static LONG rendezvous_id; - LONG rvid; - - while (!(rvid = InterlockedIncrement (&rendezvous_id))) - ; - return rvid; -} - -/* Return a new log id. These log ids are used to identify log lines - send to the same device; ie. for each CreateFile("GPG2:") a new log - id is assigned. We will ever return a log id of 0. */ -static LONG -create_log_id (void) -{ - static LONG log_id; - LONG lid; - - while (!(lid = InterlockedIncrement (&log_id))) - ; - return lid; -} - - - -pipeimpl_t -pipeimpl_new (void) -{ - pipeimpl_t pimpl; - - pimpl = malloc (sizeof (*pimpl)); - if (!pimpl) - return NULL; - - InitializeCriticalSection (&pimpl->critsect); - pimpl->refcnt = 1; - pimpl->buffer_size = 512; - pimpl->buffer = malloc (pimpl->buffer_size); - if (!pimpl->buffer) - { - DeleteCriticalSection (&pimpl->critsect); - free (pimpl); - return NULL; - } - pimpl->buffer_len = 0; - pimpl->buffer_pos = 0; - pimpl->flags = 0; - pimpl->space_available = CreateEvent (NULL, FALSE, FALSE, NULL); - if (!pimpl->space_available) - { - free (pimpl->buffer); - DeleteCriticalSection (&pimpl->critsect); - free (pimpl); - return NULL; - } - pimpl->data_available = CreateEvent (NULL, FALSE, FALSE, NULL); - if (!pimpl->data_available) - { - CloseHandle (pimpl->space_available); - free (pimpl->buffer); - DeleteCriticalSection (&pimpl->critsect); - free (pimpl); - return NULL; - } - pimpl->monitor_proc = INVALID_HANDLE_VALUE; - pimpl->monitor_access = 0; - pimpl->monitor_rvid = 0; - return pimpl; -} - - -/* PIMPL must be locked. It is unlocked at exit. */ -void -pipeimpl_unref (pipeimpl_t pimpl) -{ - int release = 0; - - if (!pimpl) - return; - - log_debug ("pipeimpl_unref (%p): dereference\n", pimpl); - - if (--pimpl->refcnt == 0) - release = 1; - LeaveCriticalSection (&pimpl->critsect); - - if (! release) - return; - - log_debug ("pipeimpl_unref (%p): release\n", pimpl); - - DeleteCriticalSection (&pimpl->critsect); - if (pimpl->buffer) - { - free (pimpl->buffer); - pimpl->buffer = NULL; - pimpl->buffer_size = 0; - } - if (pimpl->space_available != INVALID_HANDLE_VALUE) - { - CloseHandle (pimpl->space_available); - pimpl->space_available = INVALID_HANDLE_VALUE; - } - if (pimpl->data_available != INVALID_HANDLE_VALUE) - { - CloseHandle (pimpl->data_available); - pimpl->data_available = INVALID_HANDLE_VALUE; - } -} - - - -/* Allocate a new log structure. */ -logimpl_t -logimpl_new (void) -{ - logimpl_t limpl; - - limpl = calloc (1, sizeof *limpl); - if (!limpl) - return NULL; - limpl->logid = create_log_id (); - limpl->linesize = 256; - limpl->line = malloc (limpl->linesize); - if (!limpl->line) - { - free (limpl); - return NULL; - } - - return limpl; -} - - -/* There is no need to lock LIMPL, thus is a dummy function. */ -void -logimpl_unref (logimpl_t limpl) -{ - (void)limpl; -} - - -/* Flush a pending log line. */ -static void -logimpl_flush (logimpl_t limpl) -{ - if (!limpl->linelen || !enable_logging) - return; - - EnterCriticalSection (&logcontrol.lock); - if (logcontrol.filehd == INVALID_HANDLE_VALUE) - logcontrol.filehd = CreateFile (LOGFILENAME, GENERIC_WRITE, - FILE_SHARE_READ, - NULL, OPEN_ALWAYS, - FILE_ATTRIBUTE_NORMAL, NULL); - if (!logcontrol.filehd) - log_debug ("can't open log file: rc=%d\n", (int)GetLastError ()); - else - { - char buf[50]; - DWORD nwritten; - - snprintf (buf, sizeof buf, - "%06lu/%lu//", limpl->dsec % 1000000, limpl->logid); - if (!WriteFile (logcontrol.filehd, buf, strlen (buf), &nwritten, NULL)) - log_debug ("error writing log file: rc=%d\n", (int)GetLastError ()); - else if (!WriteFile (logcontrol.filehd, - limpl->line, limpl->linelen, &nwritten, NULL)) - log_debug ("error writing log file: rc=%d\n", (int)GetLastError ()); - - snprintf (buf, sizeof buf, "%s\n", limpl->truncated? "[...]":""); - if (!WriteFile (logcontrol.filehd, buf, strlen (buf), &nwritten, NULL)) - log_debug ("error writing log file: rc=%d\n", (int)GetLastError ()); - } - - LeaveCriticalSection (&logcontrol.lock); - limpl->linelen = 0; - limpl->truncated = 0; -} - - -/* Return a new opnctx handle and mark it as used. Returns NULL and - sets LastError on memory failure etc. opnctx_table_cs must be - locked on entry and is locked on exit. Note that the returned - pointer is only valid as long as opnctx_table_cs stays locked, as - it is not stable under table reallocation. */ -static opnctx_t -allocate_opnctx (int is_log) -{ - opnctx_t opnctx = NULL; - int idx; - - for (idx = 0; idx < opnctx_table_size; idx++) - if (! opnctx_table[idx].inuse) - break; - if (idx == opnctx_table_size) - { - /* We need to increase the size of the table. The approach we - take is straightforward to minimize the risk of bugs. */ - opnctx_t newtbl; - size_t newsize = opnctx_table_size + 64; - - newtbl = calloc (newsize, sizeof *newtbl); - if (!newtbl) - goto leave; - memcpy (newtbl, opnctx_table, opnctx_table_size * sizeof (*newtbl)); - free (opnctx_table); - opnctx_table = newtbl; - idx = opnctx_table_size; - opnctx_table_size = newsize; - } - opnctx = &opnctx_table[idx]; - opnctx->inuse = 1; - opnctx->is_log = is_log; - opnctx->rvid = 0; - opnctx->access_code = 0; - opnctx->share_mode = 0; - opnctx->pipeimpl = 0; - opnctx->logimpl = 0; - - leave: - return opnctx; -} - - -/* Verify context CTX, returns NULL if not valid and the pointer to - the context if valid. opnctx_table_cs must be locked on entry and - is locked on exit. Note that the returned pointer is only valid as - long as opnctx_table_cs remains locked. */ -opnctx_t -verify_opnctx (DWORD ctx_arg) -{ - opnctx_t ctx; - - if (! OPNCTX_VALID_IDX_P (ctx_arg)) - { - SetLastError (ERROR_INVALID_HANDLE); - return NULL; - } - ctx = OPNCTX_FROM_IDX (ctx_arg); - - if (! ctx->inuse) - { - SetLastError (ERROR_INVALID_HANDLE); - return NULL; - } - return ctx; -} - - -/* Return a new monitor handle and mark it as used. Returns NULL and - sets LastError on memory failure etc. opnctx_table_cs must be - locked on entry and is locked on exit. Note that the returned - pointer is only valid as long as opnctx_table_cs stays locked, as - it is not stable under table reallocation. */ -static monitor_t -allocate_monitor (void) -{ - monitor_t monitor = NULL; - int idx; - - for (idx = 0; idx < monitor_table_size; idx++) - if (! monitor_table[idx].inuse) - break; - if (idx == monitor_table_size) - { - /* We need to increase the size of the table. The approach we - take is straightforward to minimize the risk of bugs. */ - monitor_t newtbl; - size_t newsize = monitor_table_size + 16; - - newtbl = calloc (newsize, sizeof *newtbl); - if (!newtbl) - goto leave; - memcpy (newtbl, monitor_table, monitor_table_size * sizeof (*newtbl)); - free (monitor_table); - monitor_table = newtbl; - idx = monitor_table_size; - monitor_table_size = newsize; - } - monitor = &monitor_table[idx]; - monitor->inuse = 1; - monitor->pipeimpl = 0; - - leave: - return monitor; -} - - -static pipeimpl_t -assert_pipeimpl (opnctx_t ctx) -{ - DWORD ctx_arg = OPNCTX_TO_IDX (ctx); - - if (ctx->is_log) - { - log_debug (" assert_pipeimpl (ctx=%i): " - "error: not valid for a log device\n", ctx_arg); - return NULL; - } - if (! ctx->pipeimpl) - { - ctx->pipeimpl = pipeimpl_new (); - if (! ctx->pipeimpl) - { - log_debug (" assert_pipeimpl (ctx=%i): error: can't create pipe\n", - ctx_arg); - return NULL; - } - log_debug (" assert_pipeimpl (ctx=%i): created pipe 0x%p\n", - ctx_arg, ctx->pipeimpl); - } - return ctx->pipeimpl; -} - - -static logimpl_t -assert_logimpl (opnctx_t ctx) -{ - DWORD ctx_arg = OPNCTX_TO_IDX (ctx); - - if (!ctx->is_log) - { - log_debug (" assert_logimpl (ctx=%i): " - "error: not valid for a pipe device\n", ctx_arg); - return NULL; - } - if (!ctx->logimpl) - { - ctx->logimpl = logimpl_new (); - if (!ctx->logimpl) - { - log_debug (" assert_logimpl (ctx=%i): error: can't create log\n", - ctx_arg); - return NULL; - } - log_debug (" assert_logimpl (ctx=%i): created log 0x%p\n", - ctx_arg, ctx->logimpl); - } - return ctx->logimpl; -} - - -/* Verify access CODE for context CTX_ARG, returning a reference to - the locked pipe or the locked log implementation. opnctx_table_cs - must be unlocked on entry and is unlocked on exit. */ -int -access_opnctx (DWORD ctx_arg, DWORD code, pipeimpl_t *r_pipe, logimpl_t *r_log) -{ - opnctx_t ctx; - - *r_pipe = NULL; - *r_log = NULL; - - EnterCriticalSection (&opnctx_table_cs); - ctx = verify_opnctx (ctx_arg); - if (! ctx) - { - /* Error is set by verify_opnctx. */ - LeaveCriticalSection (&opnctx_table_cs); - return -1; - } - - if (! (ctx->access_code & code)) - { - SetLastError (ERROR_INVALID_ACCESS); - LeaveCriticalSection (&opnctx_table_cs); - return -1; - } - - if (ctx->is_log) - { - logimpl_t limpl; - - limpl = assert_logimpl (ctx); - if (!limpl) - { - LeaveCriticalSection (&opnctx_table_cs); - return -1; - } - *r_log = limpl; - } - else - { - pipeimpl_t pimpl; - - pimpl = assert_pipeimpl (ctx); - if (! pimpl) - { - LeaveCriticalSection (&opnctx_table_cs); - return -1; - } - EnterCriticalSection (&pimpl->critsect); - pimpl->refcnt++; - *r_pipe = pimpl; - } - - LeaveCriticalSection (&opnctx_table_cs); - return 0; -} - - - -static char * -wchar_to_utf8 (const wchar_t *string) -{ - int n; - size_t length = wcslen (string); - char *result; - - n = WideCharToMultiByte (CP_UTF8, 0, string, length, NULL, 0, NULL, NULL); - if (n < 0 || (n+1) <= 0) - abort (); - - result = malloc (n+1); - if (!result) - abort (); - n = WideCharToMultiByte (CP_ACP, 0, string, length, result, n, NULL, NULL); - if (n < 0) - abort (); - - result[n] = 0; - return result; -} - - -/* Initialize the device and return a device specific context. */ -DWORD -GPG_Init (LPCTSTR active_key, DWORD bus_context) -{ - static int firsttimedone; - HKEY handle; - wchar_t buffer[25]; - DWORD buflen; - DWORD result; - - (void)bus_context; - - EnterCriticalSection (&logcontrol.lock); - if (!firsttimedone) - { - firsttimedone++; - if (!RegOpenKeyEx (HKEY_LOCAL_MACHINE, GPGCEDEV_KEY_NAME, - 0, KEY_READ, &handle)) - { - buflen = sizeof buffer; - if (!RegQueryValueEx (handle, L"debugDriver", 0, NULL, - (PBYTE)buffer, &buflen) - && wcstol (buffer, NULL, 10) > 0) - enable_debug = 1; - RegCloseKey (handle); - } - if (!RegOpenKeyEx (HKEY_LOCAL_MACHINE, GPGCEDEV_KEY_NAME2, - 0, KEY_READ, &handle)) - { - buflen = sizeof buffer; - if (!RegQueryValueEx (handle, L"enableLog", 0, NULL, - (PBYTE)buffer, &buflen) - && wcstol (buffer, NULL, 10) > 0) - enable_logging = 1; - RegCloseKey (handle); - } - } - LeaveCriticalSection (&logcontrol.lock); - - if (enable_debug) - { - char *tmpbuf; - tmpbuf = wchar_to_utf8 (active_key); - log_debug ("GPG_Init (%s)\n", tmpbuf); - free (tmpbuf); - } - - if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, active_key, 0, KEY_READ, &handle)) - { - log_debug ("GPG_Init: error reading registry: rc=%d\n", - (int)GetLastError ()); - return 0; - } - - buflen = sizeof buffer; - if (RegQueryValueEx (handle, L"Name", 0, NULL, (PBYTE)buffer, &buflen)) - { - log_debug ("GPG_Init: error reading registry value 'Name': rc=%d\n", - (int)GetLastError ()); - result = 0; - } - else if (!wcscmp (buffer, L"GPG1:")) - { - /* This is the pipe device: We don't need any global data. - However, we need to return something. */ - log_debug ("GPG_Init: created pipe device (devctx=%p)\n", PIPECTX_VALUE); - result = PIPECTX_VALUE; - } - else if (!wcscmp (buffer, L"GPG2:")) - { - /* This is the log device. Clear the object and return something. */ - logcontrol.filehd = INVALID_HANDLE_VALUE; - log_debug ("GPG_Init: created log device (devctx=%p)\n", 0); - result = LOGCTX_VALUE; - } - else - { - if (enable_debug) - { - char *tmpbuf; - tmpbuf = wchar_to_utf8 (buffer); - log_debug ("GPG_Init: device '%s' is not supported\n", tmpbuf); - free (tmpbuf); - } - SetLastError (ERROR_DEV_NOT_EXIST); - result = 0; - } - - RegCloseKey (handle); - return result; -} - - - -/* Deinitialize this device driver. */ -BOOL -GPG_Deinit (DWORD devctx) -{ - log_debug ("GPG_Deinit (devctx=0x%p)\n", (void*)devctx); - if (devctx == PIPECTX_VALUE) - { - /* No need to release resources. */ - } - else if (devctx == LOGCTX_VALUE) - { - EnterCriticalSection (&logcontrol.lock); - if (logcontrol.filehd != INVALID_HANDLE_VALUE) - { - CloseHandle (logcontrol.filehd); - logcontrol.filehd = INVALID_HANDLE_VALUE; - } - LeaveCriticalSection (&logcontrol.lock); - } - else - { - SetLastError (ERROR_INVALID_PARAMETER); - return FALSE; /* Error. */ - } - - return TRUE; /* Success. */ -} - - - -/* Create a new open context. This function is called due to a - CreateFile from the application. */ -DWORD -GPG_Open (DWORD devctx, DWORD access_code, DWORD share_mode) -{ - opnctx_t opnctx; - DWORD ctx_arg = 0; - int is_log; - - log_debug ("GPG_Open (devctx=%p)\n", (void*)devctx); - if (devctx == PIPECTX_VALUE) - is_log = 0; - else if (devctx == LOGCTX_VALUE) - is_log = 1; - else - { - log_debug ("GPG_Open (devctx=%p): error: wrong devctx (expected 0x%p)\n", - (void*) devctx); - SetLastError (ERROR_INVALID_PARAMETER); - return 0; /* Error. */ - } - - EnterCriticalSection (&opnctx_table_cs); - opnctx = allocate_opnctx (is_log); - if (!opnctx) - { - log_debug ("GPG_Open (devctx=%p): error: could not allocate context\n", - (void*) devctx); - goto leave; - } - - opnctx->access_code = access_code; - opnctx->share_mode = share_mode; - - ctx_arg = OPNCTX_TO_IDX (opnctx); - - log_debug ("GPG_Open (devctx=%p, is_log=%d): success: created context %i\n", - (void*) devctx, is_log, ctx_arg); - if (is_log) - { - EnterCriticalSection (&logcontrol.lock); - logcontrol.references++; - LeaveCriticalSection (&logcontrol.lock); - } - - leave: - LeaveCriticalSection (&opnctx_table_cs); - return ctx_arg; -} - - - -BOOL -GPG_Close (DWORD opnctx_arg) -{ - opnctx_t opnctx; - BOOL result = FALSE; - - log_debug ("GPG_Close (ctx=%i)\n", opnctx_arg); - - EnterCriticalSection (&opnctx_table_cs); - opnctx = verify_opnctx (opnctx_arg); - if (!opnctx) - { - log_debug ("GPG_Close (ctx=%i): could not find context\n", opnctx_arg); - goto leave; - } - - if (opnctx->pipeimpl) - { - pipeimpl_t pimpl = opnctx->pipeimpl; - EnterCriticalSection (&pimpl->critsect); - /* This needs to be adjusted if there can be multiple - reader/writers. */ - if (opnctx->access_code & GENERIC_READ) - { - pimpl->flags |= PIPE_FLAG_NO_READER; - SetEvent (pimpl->space_available); - } - else if (opnctx->access_code & GENERIC_WRITE) - { - pimpl->flags |= PIPE_FLAG_NO_WRITER; - SetEvent (pimpl->data_available); - } - pipeimpl_unref (pimpl); - opnctx->pipeimpl = 0; - } - if (opnctx->logimpl) - { - logimpl_t limpl = opnctx->logimpl; - - logimpl_flush (limpl); - logimpl_unref (limpl); - free (limpl->line); - free (limpl); - opnctx->logimpl = 0; - EnterCriticalSection (&logcontrol.lock); - logcontrol.references--; - if (!logcontrol.references && logcontrol.filehd) - { - CloseHandle (logcontrol.filehd); - logcontrol.filehd = INVALID_HANDLE_VALUE; - } - LeaveCriticalSection (&logcontrol.lock); - } - opnctx->access_code = 0; - opnctx->share_mode = 0; - opnctx->rvid = 0; - opnctx->inuse = 0; - result = TRUE; - log_debug ("GPG_Close (ctx=%i): success\n", opnctx_arg); - - leave: - LeaveCriticalSection (&opnctx_table_cs); - return result; -} - - - -DWORD -GPG_Read (DWORD opnctx_arg, void *buffer, DWORD count) -{ - pipeimpl_t pimpl; - logimpl_t limpl; - const char *src; - char *dst; - int result = -1; - - log_debug ("GPG_Read (ctx=%i, buffer=0x%p, count=%d)\n", - opnctx_arg, buffer, count); - - if (access_opnctx (opnctx_arg, GENERIC_READ, &pimpl, &limpl)) - { - log_debug ("GPG_Read (ctx=%i): error: could not access context\n", - opnctx_arg); - return -1; - } - - if (limpl) - { - /* Reading from a log stream does not make sense. Return EOF. */ - result = 0; - goto leave; - } - - retry: - if (pimpl->buffer_pos == pimpl->buffer_len) - { - HANDLE data_available = pimpl->data_available; - - /* Check for end of file. */ - if (pimpl->flags & PIPE_FLAG_NO_WRITER) - { - log_debug ("GPG_Read (ctx=%i): success: EOF\n", opnctx_arg); - result = 0; - goto leave; - } - - /* Check for request to unblock once. */ - if (pimpl->flags & PIPE_FLAG_UNBLOCK_READER) - { - log_debug ("GPG_Read (ctx=%i): success: EBUSY (due to unblock)\n", - opnctx_arg); - pimpl->flags &= ~PIPE_FLAG_UNBLOCK_READER; - SetLastError (ERROR_BUSY); - result = -1; - goto leave; - } - - LeaveCriticalSection (&pimpl->critsect); - log_debug ("GPG_Read (ctx=%i): waiting: data_available\n", opnctx_arg); - WaitForSingleObject (data_available, INFINITE); - log_debug ("GPG_Read (ctx=%i): resuming: data_available\n", opnctx_arg); - EnterCriticalSection (&pimpl->critsect); - goto retry; - } - - dst = buffer; - src = pimpl->buffer + pimpl->buffer_pos; - while (count > 0 && pimpl->buffer_pos < pimpl->buffer_len) - { - *dst++ = *src++; - count--; - pimpl->buffer_pos++; - } - result = (dst - (char*)buffer); - if (pimpl->buffer_pos == pimpl->buffer_len) - pimpl->buffer_pos = pimpl->buffer_len = 0; - - /* Now there should be some space available. Signal the write end. - Even if COUNT was passed as NULL and no space is available, - signaling must be done. */ - if (!SetEvent (pimpl->space_available)) - log_debug ("GPG_Read (ctx=%i): warning: SetEvent(space_available) " - "failed: rc=%d\n", opnctx_arg, (int)GetLastError ()); - - log_debug ("GPG_Read (ctx=%i): success: result=%d\n", opnctx_arg, result); - - leave: - pipeimpl_unref (pimpl); - logimpl_unref (limpl); - return result; -} - - - -DWORD -GPG_Write (DWORD opnctx_arg, const void *buffer, DWORD count) -{ - pipeimpl_t pimpl; - logimpl_t limpl; - int result = -1; - const char *src; - char *dst; - size_t nwritten = 0; - - log_debug ("GPG_Write (ctx=%i, buffer=0x%p, count=%d)\n", opnctx_arg, - buffer, count); - - if (access_opnctx (opnctx_arg, GENERIC_WRITE, &pimpl, &limpl)) - { - log_debug ("GPG_Write (ctx=%i): error: could not access context\n", - opnctx_arg); - return -1; - } - - if (!count) - { - log_debug ("GPG_Write (ctx=%i): success\n", opnctx_arg); - result = 0; - goto leave; - } - - retry: - if (limpl) - { - /* Store it in our buffer up to a LF and print complete lines. */ - result = count; - if (!limpl->linelen) - limpl->dsec = GetTickCount () / 100; - dst = limpl->line + limpl->linelen; - for (src = buffer; count; count--, src++) - { - if (*src == '\n') - { - logimpl_flush (limpl); - dst = limpl->line + limpl->linelen; - } - else if (limpl->linelen >= limpl->linesize) - limpl->truncated = 1; - else - { - *dst++ = *src; - limpl->linelen++; - } - } - } - else /* pimpl */ - { - /* Check for broken pipe. */ - if (pimpl->flags & PIPE_FLAG_NO_READER) - { - log_debug ("GPG_Write (ctx=%i): error: broken pipe\n", opnctx_arg); - SetLastError (ERROR_BROKEN_PIPE); - goto leave; - } - - /* Check for request to unblock once. */ - if (pimpl->flags & PIPE_FLAG_UNBLOCK_WRITER) - { - log_debug ("GPG_Write (ctx=%i): success: EBUSY (due to unblock)\n", - opnctx_arg); - pimpl->flags &= ~PIPE_FLAG_UNBLOCK_WRITER; - SetLastError (ERROR_BUSY); - result = -1; - goto leave; - } - - /* Write to our buffer. */ - if (pimpl->buffer_len == pimpl->buffer_size) - { - /* Buffer is full. */ - HANDLE space_available = pimpl->space_available; - LeaveCriticalSection (&pimpl->critsect); - log_debug ("GPG_Write (ctx=%i): waiting: space_available\n", - opnctx_arg); - WaitForSingleObject (space_available, INFINITE); - log_debug ("GPG_Write (ctx=%i): resuming: space_available\n", - opnctx_arg); - EnterCriticalSection (&pimpl->critsect); - goto retry; - } - - src = buffer; - dst = pimpl->buffer + pimpl->buffer_len; - while (count > 0 && pimpl->buffer_len < pimpl->buffer_size) - { - *dst++ = *src++; - count--; - pimpl->buffer_len++; - nwritten++; - } - result = nwritten; - - if (!SetEvent (pimpl->data_available)) - log_debug ("GPG_Write (ctx=%i): warning: SetEvent(data_available) " - "failed: rc=%d\n", opnctx_arg, (int)GetLastError ()); - } - - log_debug ("GPG_Write (ctx=%i): success: result=%d\n", opnctx_arg, result); - - leave: - pipeimpl_unref (pimpl); - logimpl_unref (limpl); - return result; -} - - - -DWORD -GPG_Seek (DWORD opnctx_arg, long amount, WORD type) -{ - SetLastError (ERROR_SEEK_ON_DEVICE); - return -1; /* Error. */ -} - - - -/* opnctx_table_s is locked on entering and on exit. */ -static BOOL -make_pipe (opnctx_t ctx, LONG rvid) -{ - DWORD ctx_arg = OPNCTX_TO_IDX (ctx); - opnctx_t peerctx = NULL; - int idx; - pipeimpl_t pimpl; - - log_debug (" make_pipe (ctx=%i, rvid=%08lx)\n", ctx_arg, rvid); - - if (ctx->pipeimpl) - { - log_debug (" make_pipe (ctx=%i): error: already assigned\n", ctx_arg); - SetLastError (ERROR_ALREADY_ASSIGNED); - return FALSE; - } - - /* GnuPG and other programs don't use the safe ASSIGN_RVID call - because they guarantee that the context exists during the whole - time the child process runs. GPGME is more asynchronous and - relies on ASSIGN_RVID monitors. So, first check for open - contexts, then check for monitors. */ - - for (idx = 0; idx < opnctx_table_size; idx++) - if (opnctx_table[idx].inuse && opnctx_table[idx].rvid == rvid) - { - peerctx = &opnctx_table[idx]; - break; - } - if (peerctx) - { - /* This is the GnuPG etc case, where the context is still open. - It may also cover the GPGME case if GPGME is still using its - own end of the pipe at the time of this call. */ - if (peerctx == ctx) - { - log_debug (" make_pipe (ctx=%i): error: target and source identical\n", - ctx_arg); - SetLastError (ERROR_INVALID_TARGET_HANDLE); - return FALSE; - } - - if ((ctx->access_code & GENERIC_READ)) - { - /* Check that the peer is a write end. */ - if (!(peerctx->access_code & GENERIC_WRITE)) - { - log_debug (" make_pipe (ctx=%i): error: peer is not writer\n", - ctx_arg); - SetLastError (ERROR_INVALID_ACCESS); - return FALSE; - } - } - else if ((ctx->access_code & GENERIC_WRITE)) - { - /* Check that the peer is a read end. */ - if (!(peerctx->access_code & GENERIC_READ)) - { - log_debug (" make_pipe (ctx=%i): error: peer is not reader\n", - ctx_arg); - SetLastError (ERROR_INVALID_ACCESS); - return FALSE; - } - } - else - { - log_debug (" make_pipe (ctx=%i): error: invalid access\n", ctx_arg); - SetLastError (ERROR_INVALID_ACCESS); - return FALSE; - } - - /* Make sure the peer has a pipe implementation to be shared. If - not yet, create one. */ - pimpl = assert_pipeimpl (peerctx); - if (! pimpl) - return FALSE; - } - else - { - /* This is the case where ASSIGN_RVID was called to create a - monitor, and the pipe is already closed at the parent side. - For example GPGME verify detached plain text, where GPG calls - MAKE_PIPE very late. */ - - for (idx = 0; idx < monitor_table_size; idx++) - if (monitor_table[idx].inuse - && monitor_table[idx].pipeimpl->monitor_rvid == rvid) - { - pimpl = monitor_table[idx].pipeimpl; - break; - } - if (idx == monitor_table_size) - { - log_debug (" make_pipe (ctx=%i): error: not found\n", ctx_arg); - SetLastError (ERROR_NOT_FOUND); - return FALSE; - } - - if (ctx->access_code & GENERIC_READ) - { - /* Check that the peer is a write end. */ - if (!(pimpl->monitor_access & GENERIC_READ)) - { - log_debug (" make_pipe (ctx=%i): error: monitor is not reader\n", - ctx_arg); - SetLastError (ERROR_INVALID_ACCESS); - return FALSE; - } - } - else if ((ctx->access_code & GENERIC_WRITE)) - { - /* Check that the peer is a read end. */ - if (!(pimpl->monitor_access & GENERIC_WRITE)) - { - log_debug (" make_pipe (ctx=%i): error: monitor is not writer\n", - ctx_arg); - SetLastError (ERROR_INVALID_ACCESS); - return FALSE; - } - } - else - { - log_debug (" make_pipe (ctx=%i): error: invalid access\n", ctx_arg); - SetLastError (ERROR_INVALID_ACCESS); - return FALSE; - } - } - - EnterCriticalSection (&pimpl->critsect); - pimpl->refcnt++; - if (pimpl->monitor_proc != INVALID_HANDLE_VALUE) - { - /* If there is a monitor to the pipe, then it's now about time - to ask it to go away. */ - log_debug (" make_pipe (ctx=%i): waking up monitor for pipe 0x%p\n", - ctx_arg, pimpl); - pimpl->flags |= PIPE_FLAG_HALT_MONITOR; - if (pimpl->monitor_access & GENERIC_READ) - SetEvent (pimpl->data_available); - else - SetEvent (pimpl->space_available); - } - LeaveCriticalSection (&pimpl->critsect); - - ctx->pipeimpl = pimpl; - - if (peerctx) - { - log_debug (" make_pipe (ctx=%i): success: combined with peer ctx=%i " - "(pipe 0x%p)\n", ctx_arg, OPNCTX_TO_IDX (peerctx), pimpl); - } - else - { - log_debug (" make_pipe (ctx=%i): success: combined with " - "pipe 0x%p\n", ctx_arg, OPNCTX_TO_IDX (peerctx), pimpl); - } - - return TRUE; -} - - -/* opnctx_table_s is locked on entering and on exit. */ -static BOOL -unblock_call (opnctx_t ctx) -{ - /* If there is no pipe object, no thread can be blocked. */ - if (!ctx->pipeimpl) - return TRUE; - - EnterCriticalSection (&ctx->pipeimpl->critsect); - if (ctx->access_code & GENERIC_READ) - { - ctx->pipeimpl->flags |= PIPE_FLAG_UNBLOCK_READER; - SetEvent (ctx->pipeimpl->data_available); - } - else if (ctx->access_code & GENERIC_WRITE) - { - ctx->pipeimpl->flags |= PIPE_FLAG_UNBLOCK_WRITER; - SetEvent (ctx->pipeimpl->space_available); - } - LeaveCriticalSection (&ctx->pipeimpl->critsect); - - return TRUE; -} - - -static DWORD CALLBACK -monitor_main (void *arg) -{ - pipeimpl_t pimpl = (pipeimpl_t) arg; - HANDLE handles[2]; - int idx; - - log_debug ("starting monitor (pimpl=0x%p)\n", pimpl); - - EnterCriticalSection (&pimpl->critsect); - /* Putting proc first in the array is convenient, as this is a hard - break-out condition (and thus takes precedence in WFMO). The - reader/writer event is a soft condition, which also requires a - flag to be set. */ - handles[0] = pimpl->monitor_proc; - if (pimpl->monitor_access & GENERIC_READ) - handles[1] = pimpl->data_available; - else - handles[1] = pimpl->space_available; - - retry: - /* First check if the peer has not gone away. If it has, we are done. */ - if (pimpl->flags & PIPE_FLAG_HALT_MONITOR) - { - log_debug ("monitor (pimpl=0x%p): done: monitored process taking over\n", - pimpl); - } - else - { - DWORD res; - - LeaveCriticalSection (&pimpl->critsect); - log_debug ("monitor (pimpl=0x%p): waiting\n", pimpl); - res = WaitForMultipleObjects (2, handles, FALSE, INFINITE); - log_debug ("monitor (pimpl=0x%p): resuming\n", pimpl); - EnterCriticalSection (&pimpl->critsect); - - if (res == WAIT_FAILED) - { - log_debug ("monitor (pimpl=0x%p): WFMO failed: %i\n", - pimpl, GetLastError ()); - } - else if (res == WAIT_OBJECT_0) - { - log_debug ("monitor (pimpl=0x%p): done: monitored process died\n", - pimpl); - } - else if (res == WAIT_OBJECT_0 + 1) - goto retry; - else - { - log_debug ("monitor (pimpl=0x%p): unexpected result of WFMO: %i\n", - pimpl, res); - } - } - - log_debug ("ending monitor (pimpl=0x%p)\n", pimpl); - - /* Remove the monitor from the monitor table. */ - LeaveCriticalSection (&pimpl->critsect); - EnterCriticalSection (&opnctx_table_cs); - for (idx = 0; idx < monitor_table_size; idx++) - if (monitor_table[idx].inuse - && monitor_table[idx].pipeimpl == pimpl) - { - monitor_table[idx].pipeimpl = NULL; - monitor_table[idx].inuse = 0; - break; - } - if (idx == monitor_table_size) - log_debug ("can not find monitor in table (pimpl=0x%p)\n", pimpl); - LeaveCriticalSection (&opnctx_table_cs); - EnterCriticalSection (&pimpl->critsect); - - /* Now do the rest of the cleanup. */ - CloseHandle (pimpl->monitor_proc); - pimpl->monitor_proc = INVALID_HANDLE_VALUE; - pimpl->monitor_access = 0; - pimpl->monitor_rvid = 0; - pimpl->flags &= ~PIPE_FLAG_HALT_MONITOR; - pipeimpl_unref (pimpl); - - return 0; -} - - -/* opnctx_table_s is locked on entering and on exit. */ -static BOOL -assign_rvid (opnctx_t ctx, DWORD rvid, DWORD pid) -{ - DWORD ctx_arg = OPNCTX_TO_IDX (ctx); - int idx; - opnctx_t peerctx; - HANDLE monitor_hnd; - HANDLE proc; - pipeimpl_t pimpl; - monitor_t monitor; - - log_debug (" assign_rvid (ctx=%i, rvid=%08lx, pid=%08lx)\n", - ctx_arg, rvid, pid); - - for (idx = 0; idx < opnctx_table_size; idx++) - if (opnctx_table[idx].inuse && opnctx_table[idx].rvid == rvid) - { - peerctx = &opnctx_table[idx]; - break; - } - if (! peerctx) - { - log_debug (" assign_rvid (ctx=%i): error: not found\n", ctx_arg); - SetLastError (ERROR_NOT_FOUND); - return FALSE; - } - - if (peerctx->pipeimpl - && peerctx->pipeimpl->monitor_proc != INVALID_HANDLE_VALUE) - { - log_debug (" assign_rvid (ctx=%i): error: rvid already assigned\n", - ctx_arg); - SetLastError (ERROR_ALREADY_ASSIGNED); - return FALSE; - } - - proc = OpenProcess (0, FALSE, pid); - if (proc == NULL) - { - log_debug (" assign_rvid (ctx=%i): error: process not found\n", - ctx_arg); - return FALSE; - } - - /* Acquire a reference to the pipe. We don't want accesss to be - checked. */ - pimpl = assert_pipeimpl (peerctx); - if (! pimpl) - { - CloseHandle (proc); - return FALSE; - } - - monitor = allocate_monitor (); - if (!monitor) - { - log_debug (" assign_rvid (ctx=%i): error: could not allocate monitor\n", - ctx_arg); - CloseHandle (proc); - return FALSE; - } - monitor->pipeimpl = pimpl; - - EnterCriticalSection (&pimpl->critsect); - pimpl->refcnt++; - - /* The monitor shadows the peer, so it takes its access. Our access - is the opposite of that of the peer. */ - pimpl->monitor_proc = proc; - if (peerctx->access_code == GENERIC_READ) - pimpl->monitor_access = GENERIC_WRITE; - else - pimpl->monitor_access = GENERIC_READ; - pimpl->monitor_rvid = rvid; - - monitor_hnd = CreateThread (NULL, 0, monitor_main, pimpl, 0, NULL); - if (monitor_hnd == INVALID_HANDLE_VALUE) - { - pimpl->monitor_access = 0; - pimpl->monitor_proc = INVALID_HANDLE_VALUE; - LeaveCriticalSection (&pimpl->critsect); - - monitor->pipeimpl = NULL; - monitor->inuse = 0; - - CloseHandle (proc); - log_debug (" assign_rvid (ctx=%i): error: can not create monitor\n", - ctx_arg); - return FALSE; - } - CloseHandle (monitor_hnd); - - /* Consume the pimpl reference. */ - LeaveCriticalSection (&pimpl->critsect); - - return TRUE; -} - - -BOOL -GPG_IOControl (DWORD opnctx_arg, DWORD code, void *inbuf, DWORD inbuflen, - void *outbuf, DWORD outbuflen, DWORD *actualoutlen) -{ - opnctx_t opnctx; - BOOL result = FALSE; - LONG rvid; - LONG pid; - - log_debug ("GPG_IOControl (ctx=%i, %08x)\n", opnctx_arg, code); - - EnterCriticalSection (&opnctx_table_cs); - opnctx = verify_opnctx (opnctx_arg); - if (!opnctx) - { - log_debug ("GPG_IOControl (ctx=%i): error: could not access context\n", - opnctx_arg); - goto leave; - } - if (opnctx->is_log) - { - log_debug ("GPG_IOControl (ctx=%i): error: invalid code %u" - " for log device\n", opnctx_arg, (unsigned int)code); - SetLastError (ERROR_INVALID_PARAMETER); - goto leave; - } - - switch (code) - { - case GPGCEDEV_IOCTL_GET_RVID: - log_debug ("GPG_IOControl (ctx=%i): code: GET_RVID\n", opnctx_arg); - if (inbuf || inbuflen || !outbuf || outbuflen < sizeof (LONG)) - { - log_debug ("GPG_IOControl (ctx=%i): error: invalid parameter\n", - opnctx_arg); - SetLastError (ERROR_INVALID_PARAMETER); - goto leave; - } - - if (! opnctx->rvid) - opnctx->rvid = create_rendezvous_id (); - log_debug ("GPG_IOControl (ctx=%i): returning rvid: %08lx\n", - opnctx_arg, opnctx->rvid); - - memcpy (outbuf, &opnctx->rvid, sizeof (LONG)); - if (actualoutlen) - *actualoutlen = sizeof (LONG); - result = TRUE; - break; - - case GPGCEDEV_IOCTL_MAKE_PIPE: - log_debug ("GPG_IOControl (ctx=%i): code: MAKE_PIPE\n", opnctx_arg); - if (!inbuf || inbuflen < sizeof (LONG) - || outbuf || outbuflen || actualoutlen) - { - log_debug ("GPG_IOControl (ctx=%i): error: invalid parameter\n", - opnctx_arg); - SetLastError (ERROR_INVALID_PARAMETER); - goto leave; - } - memcpy (&rvid, inbuf, sizeof (LONG)); - log_debug ("GPG_IOControl (ctx=%i): make pipe for rvid: %08lx\n", - opnctx_arg, rvid); - if (make_pipe (opnctx, rvid)) - result = TRUE; - break; - - case GPGCEDEV_IOCTL_UNBLOCK: - log_debug ("GPG_IOControl (ctx=%i): code: UNBLOCK\n", opnctx_arg); - if (inbuf || inbuflen || outbuf || outbuflen || actualoutlen) - { - log_debug ("GPG_IOControl (ctx=%i): error: invalid parameter\n", - opnctx_arg); - SetLastError (ERROR_INVALID_PARAMETER); - goto leave; - } - - if (unblock_call (opnctx)) - result = TRUE; - break; - - case GPGCEDEV_IOCTL_ASSIGN_RVID: - log_debug ("GPG_IOControl (ctx=%i): code: ASSIGN_RVID\n", opnctx_arg); - if (!inbuf || inbuflen < 2 * sizeof (DWORD) - || outbuf || outbuflen || actualoutlen) - { - log_debug ("GPG_IOControl (ctx=%i): error: invalid parameter\n", - opnctx_arg); - SetLastError (ERROR_INVALID_PARAMETER); - goto leave; - } - memcpy (&rvid, inbuf, sizeof (DWORD)); - memcpy (&pid, ((char *) inbuf) + sizeof (DWORD), sizeof (DWORD)); - log_debug ("GPG_IOControl (ctx=%i): assign rvid %08lx to pid %08lx\n", - opnctx_arg, rvid, pid); - if (assign_rvid (opnctx, rvid, pid)) - result = TRUE; - break; - - case IOCTL_PSL_NOTIFY: - /* This notification is received if the application's main - thread exits and the application has other threads running - and the application has open handles for this device. What - we do is to unblock them all simialr to an explicit unblock - call. */ - log_debug ("GPG_IOControl (ctx=%i): code: NOTIFY\n", opnctx_arg); - - if (unblock_call (opnctx)) - result = TRUE; - break; - - default: - log_debug ("GPG_IOControl (ctx=%i): code: (unknown)\n", opnctx_arg); - SetLastError (ERROR_INVALID_PARAMETER); - break; - } - - log_debug ("GPG_IOControl (ctx=%i): success: result=%d\n", opnctx_arg, - result); - - leave: - LeaveCriticalSection (&opnctx_table_cs); - return result; -} - - - -void -GPG_PowerUp (DWORD devctx) -{ - log_debug ("GPG_PowerUp (devctx=%i)\n", devctx); -} - - - -void -GPG_PowerDown (DWORD devctx) -{ - log_debug ("GPG_PowerDown (devctx=%i)\n", devctx); -} - - - - - -/* Entry point called by the DLL loader. */ -int WINAPI -DllMain (HINSTANCE hinst, DWORD reason, LPVOID reserved) -{ - (void)reserved; - - switch (reason) - { - case DLL_PROCESS_ATTACH: - InitializeCriticalSection (&opnctx_table_cs); - InitializeCriticalSection (&logcontrol.lock); - break; - - case DLL_THREAD_ATTACH: - break; - - case DLL_THREAD_DETACH: - break; - - case DLL_PROCESS_DETACH: - DeleteCriticalSection (&opnctx_table_cs); - break; - - default: - break; - } - - return TRUE; -} diff --git a/src/gpgcedev.def b/src/gpgcedev.def deleted file mode 100644 index bc52d3a..0000000 --- a/src/gpgcedev.def +++ /dev/null @@ -1,34 +0,0 @@ -; gpgcedev.def - List of symbols to export for gpgcedev. -; Copyright (C) 2010 Free Software Foundation, Inc. -; -; This file is part of Assuan. -; -; Assuan is free software; you can redistribute it and/or modify it -; under the terms of 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. -; -; Assuan 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 -; Lesser General Public License for more details. -; -; You should have received a copy of the GNU Lesser General Public -; License along with this program; if not, see . -; SPDX-License-Identifier: LGPL-3.0+ - - -EXPORTS - GPG_Init - GPG_Deinit - GPG_Open - GPG_Close - GPG_Read - GPG_Write - GPG_Seek - GPG_IOControl - GPG_PowerUp - GPG_PowerDown - -; END - diff --git a/src/gpgcemgr.c b/src/gpgcemgr.c deleted file mode 100644 index 5b4f56e..0000000 --- a/src/gpgcemgr.c +++ /dev/null @@ -1,608 +0,0 @@ -/* gpgcempr.c - Manager for GPG CE devices - * Copyright (C) 2010 Free Software Foundation, Inc. - * - * This file is part of Assuan. - * - * Assuan is free software; you can redistribute it and/or modify it - * under the terms of 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. - * - * Assuan 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see . - * SPDX-License-Identifier: LGPL-3.0+ - */ - -#define _WIN32_WCE 0x0500 - -#include -#include - -#define PGM "gpgcemgr" - -#define GPGCEDEV_KEY_NAME L"Drivers\\GnuPG_Device" -#define GPGCEDEV_KEY_NAME2 L"Drivers\\GnuPG_Log" -#define GPGCEDEV_DLL_NAME L"gpgcedev.dll" -#define GPGCEDEV_PREFIX L"GPG" - - -static char * -wchar_to_utf8 (const wchar_t *string) -{ - int n; - size_t length = wcslen (string); - char *result; - - n = WideCharToMultiByte (CP_UTF8, 0, string, length, NULL, 0, NULL, NULL); - if (n < 0 || (n+1) <= 0) - abort (); - - result = malloc (n+1); - if (!result) - abort (); - n = WideCharToMultiByte (CP_ACP, 0, string, length, result, n, NULL, NULL); - if (n < 0) - abort (); - - result[n] = 0; - return result; -} - - -static wchar_t * -utf8_to_wchar (const char *string) -{ - int n; - size_t nbytes; - wchar_t *result; - - if (!string) - abort (); - - n = MultiByteToWideChar (CP_UTF8, 0, string, -1, NULL, 0); - if (n < 0) - abort (); - nbytes = (size_t)(n+1) * sizeof(*result); - if (nbytes / sizeof(*result) != (n+1)) - abort (); - result = malloc (nbytes); - if (!result) - abort (); - - n = MultiByteToWideChar (CP_UTF8, 0, string, -1, result, n); - if (n < 0) - abort (); - return result; -} - - -static int -install (void) -{ - HKEY handle; - DWORD disp, dw; - int rc; - - if ((rc=RegCreateKeyEx (HKEY_LOCAL_MACHINE, GPGCEDEV_KEY_NAME, 0, NULL, 0, - KEY_WRITE, NULL, &handle, &disp))) - { - fprintf (stderr, PGM": error creating registry key 1: rc=%d\n", rc); - return 1; - } - - RegSetValueEx (handle, L"dll", 0, REG_SZ, - (void*)GPGCEDEV_DLL_NAME, sizeof (GPGCEDEV_DLL_NAME)); - RegSetValueEx (handle, L"prefix", 0, REG_SZ, - (void*)GPGCEDEV_PREFIX, sizeof (GPGCEDEV_PREFIX)); - - dw = 1; - RegSetValueEx (handle, L"Index", 0, REG_DWORD, (void*)&dw, sizeof dw); - - RegCloseKey (handle); - - fprintf (stderr, PGM": registry key 1 created\n"); - - if ((rc=RegCreateKeyEx (HKEY_LOCAL_MACHINE, GPGCEDEV_KEY_NAME2, 0, NULL, 0, - KEY_WRITE, NULL, &handle, &disp))) - { - fprintf (stderr, PGM": error creating registry key 2: rc=%d\n", rc); - return 1; - } - - RegSetValueEx (handle, L"dll", 0, REG_SZ, - (void*)GPGCEDEV_DLL_NAME, sizeof (GPGCEDEV_DLL_NAME)); - RegSetValueEx (handle, L"prefix", 0, REG_SZ, - (void*)GPGCEDEV_PREFIX, sizeof (GPGCEDEV_PREFIX)); - - dw = 2; - RegSetValueEx (handle, L"Index", 0, REG_DWORD, (void*)&dw, sizeof dw); - - RegCloseKey (handle); - - fprintf (stderr, PGM": registry key 2 created\n"); - - - return 0; -} - - -static int -deinstall (wchar_t *name) -{ - int result = 0; - HANDLE shd; - DEVMGR_DEVICE_INFORMATION dinfo; - - memset (&dinfo, 0, sizeof dinfo); - dinfo.dwSize = sizeof dinfo; - shd = FindFirstDevice (DeviceSearchByLegacyName, name, &dinfo); - if (shd == INVALID_HANDLE_VALUE) - { - if (GetLastError () == 18) - fprintf (stderr, PGM": device not found\n"); - else - { - fprintf (stderr, PGM": FindFirstDevice failed: rc=%d\n", - (int)GetLastError ()); - result = 1; - } - } - else - { - fprintf (stderr, PGM": ActivateDevice handle is %p\n", dinfo.hDevice); - if (dinfo.hDevice && dinfo.hDevice != INVALID_HANDLE_VALUE) - { - if (!DeactivateDevice (dinfo.hDevice)) - { - fprintf (stderr, PGM": DeactivateDevice failed: rc=%d\n", - (int)GetLastError ()); - result = 1; - } - else - fprintf (stderr, PGM": DeactivateDevice succeeded\n"); - } - FindClose (shd); - } - - return result; -} - - -static int -enable_debug (int yes) -{ - HKEY handle; - DWORD disp; - int rc; - - if ((rc=RegCreateKeyEx (HKEY_LOCAL_MACHINE, GPGCEDEV_KEY_NAME, 0, NULL, 0, - KEY_WRITE, NULL, &handle, &disp))) - { - fprintf (stderr, PGM": error creating debug registry key: rc=%d\n", rc); - return 1; - } - - RegSetValueEx (handle, L"debugDriver", 0, REG_SZ, - (void*)(yes? L"1":L"0"), sizeof L"0"); - RegCloseKey (handle); - return 0; -} - - -static int -enable_log (int yes) -{ - HKEY handle; - DWORD disp; - int rc; - - if ((rc=RegCreateKeyEx (HKEY_LOCAL_MACHINE, GPGCEDEV_KEY_NAME2, 0, NULL, 0, - KEY_WRITE, NULL, &handle, &disp))) - { - fprintf (stderr, PGM": error creating debug registry key: rc=%d\n", rc); - return 1; - } - - RegSetValueEx (handle, L"enableLog", 0, REG_SZ, - (void*)(yes? L"1":L"0"), sizeof L"0"); - RegCloseKey (handle); - return 0; -} - - - -/* Kudos to Scott Seligman for his work - on the reverse engineering. */ -struct htc_sensor_s -{ - SHORT tilt_x; // From -1000 to 1000 (about), 0 is flat - SHORT tilt_y; // From -1000 to 1000 (about), 0 is flat - SHORT tilt_z; // From -1000 to 1000 (about) - DWORD angle_x; // 0 .. 359 - DWORD angle_y; // From 0 to 359 - DWORD orientation; // 0.. 5? - DWORD unknown; // Handle? -}; -typedef struct htc_sensor_s *htc_sensor_t; - -static HANDLE (WINAPI *HTCSensorOpen) (DWORD); -static void (WINAPI *HTCSensorClose) (HANDLE); -static DWORD (WINAPI *HTCSensorGetDataOutput) (HANDLE, htc_sensor_t); - -static int -load_sensor_api (void) -{ - static HMODULE dll_hd; - - if (dll_hd) - return 0; - - dll_hd = LoadLibrary (L"HTCSensorSDK.dll"); - if (!dll_hd) - { - fprintf (stderr, PGM": error loading sensor DLL: rc=%d\n", - (int)GetLastError ()); - return 1; - } - - HTCSensorOpen = (void*)GetProcAddress (dll_hd, L"HTCSensorOpen"); - if (HTCSensorOpen) - HTCSensorClose = (void*)GetProcAddress (dll_hd, L"HTCSensorClose"); - if (HTCSensorClose) - HTCSensorGetDataOutput = (void*) - GetProcAddress (dll_hd, L"HTCSensorGetDataOutput"); - if (!HTCSensorGetDataOutput) - { - fprintf (stderr, PGM": error loading function from sensor DLL: rc=%d\n", - (int)GetLastError ()); - CloseHandle (dll_hd); - return 1; - } - return 0; -} - - -static int -gravity (void) -{ - int rc; - HANDLE sensor; - struct htc_sensor_s lastdata; - struct htc_sensor_s data; - - rc = load_sensor_api (); - if (rc) - return rc; - - sensor = HTCSensorOpen (1 /* tilt sensor */); - if (!sensor || sensor == INVALID_HANDLE_VALUE) - { - fprintf (stderr, PGM": error opening gravity sensor: rc=%d\n", - (int)GetLastError ()); - HTCSensorClose (sensor); - return 1; - } - - memset (&lastdata, 0, sizeof lastdata); - while (HTCSensorGetDataOutput (sensor, &data)) - { - if (lastdata.tilt_x/10 != data.tilt_x/10 - || lastdata.tilt_y/10 != data.tilt_y/10 - || lastdata.tilt_z/10 != data.tilt_z/10 - || lastdata.angle_x/5 != data.angle_x/5 - || lastdata.angle_y/5 != data.angle_y/5 - || lastdata.orientation != data.orientation) - { - lastdata = data; - printf ("tilt: x=%-5d y=%-5d z=%-5d " - "angle: x=%-3d y=%-3d " - "ori: %d\n", - (int)data.tilt_x, (int)data.tilt_y, (int)data.tilt_z, - (int)data.angle_x, (int)data.angle_y, - (int)data.orientation); - } - Sleep (200); - } - fprintf (stderr, PGM": reading sensor data failed: rc=%d\n", - (int)GetLastError ()); - HTCSensorClose (sensor); - return 0; -} - - - -/* No GPD1 device on the HTC Touch Pro 2. */ -# if 0 -static int -gps_raw (void) -{ - HANDLE hd; - char buffer[1000]; - unsigned long nread; - int count; - - hd = CreateFile (L"GPD1:", GENERIC_READ, FILE_SHARE_READ, - NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if (hd == INVALID_HANDLE_VALUE) - { - fprintf (stderr, PGM": can't open `GPD1': rc=%d\n", - (int)GetLastError ()); - return 1; - } - fprintf (stderr, PGM": GPS device successfully opened\n"); - - for (count=0; count < 100; count++) - { - if (!ReadFile (hd, buffer, sizeof buffer-1, &nread, NULL)) - { - fprintf (stderr, PGM": error reading `GPD1': rc=%d\n", - (int)GetLastError ()); - CloseHandle (hd); - return 1; - } - buffer[nread-1] = 0; - fputs (buffer, stdout); - } - - CloseHandle (hd); - return 0; -} -#endif - -/* Untested samples for CE6. */ -#if 0 -static int -gps (void) -{ - HANDLE hd; - GPS_POSITION pos; - - hd = GPSOpenDevice (NULL, NULL, NULL, 0); - if (hd == INVALID_HANDLE_VALUE) - { - fprintf (stderr, PGM": GPSOpenDevice failed: rc=%d\n", - (int)GetLastError ()); - return 1; - } - fprintf (stderr, PGM": GPS device successfully opened\n"); - - if (GPSGetPosition (hd, &pos, 2000, 0)) - { - fprintf (stderr, PGM": GPSGetPosition failed: rc=%d\n", - (int)GetLastError ()); - GPSCloseDevice (hd); - return 1; - } - - - GPSCloseDevice (hd); - return 0; -} -#endif - - -static void -set_show_registry (const wchar_t *key, const wchar_t *name, const char *value) -{ - HKEY handle; - DWORD disp, nbytes, n1, type; - int rc; - - if ((rc=RegCreateKeyEx (HKEY_LOCAL_MACHINE, key, 0, NULL, 0, - KEY_WRITE, NULL, &handle, &disp))) - { - fprintf (stderr, PGM": error creating registry key: rc=%d\n", rc); - return; - } - - if (value && !stricmp (value, "none")) - { - if ((rc=RegDeleteValue (handle, name))) - fprintf (stderr, PGM": error deleting registry value: rc=%d\n", rc); - } - else if (value) - { - wchar_t *tmp = utf8_to_wchar (value); - if ((rc=RegSetValueEx (handle, name, 0, REG_SZ, - (void*)tmp, wcslen (tmp)*sizeof(wchar_t)))) - fprintf (stderr, PGM": error setting registry value: rc=%d\n", rc); - free (tmp); - } - else - { - nbytes = 2; - if ((rc=RegQueryValueEx (handle, name, 0, NULL, NULL, &nbytes))) - { - if (rc == ERROR_FILE_NOT_FOUND) - fprintf (stderr, PGM": registry value not set\n"); - else - fprintf (stderr, PGM": error reading registry value: rc=%d\n", rc); - } - else - { - char *result = malloc ((n1=nbytes+2)); - if (!result) - fprintf (stderr, PGM": malloc failed: rc=%d\n", - (int)GetLastError ()); - else if ((rc=RegQueryValueEx (handle, name, 0, &type, - (void*)result, &n1))) - { - fprintf (stderr, PGM": error reading registry value (2): " - "rc=%d\n", rc); - free (result); - } - else - { - result[nbytes] = 0; /* Make sure it is a string. */ - result[nbytes+1] = 0; - if (type == REG_SZ) - { - wchar_t *tmp = (void*)result; - result = wchar_to_utf8 (tmp); - free (tmp); - printf ("%s\n", result); - } - else - fprintf (stderr, PGM": registry value is not a string\n"); - free (result); - } - } - } - - RegCloseKey (handle); -} - - - -int -main (int argc, char **argv) -{ - int result = 0; - - if (argc > 1 && !strcmp (argv[1], "--register")) - result = install (); - else if (argc > 1 && !strcmp (argv[1], "--deactivate")) - { - if (deinstall (L"GPG1:")) - result = 1; - if (deinstall (L"GPG2:")) - result = 1; - } - else if (argc > 1 && !strcmp (argv[1], "--activate")) - { - HANDLE hd; - - /* This is mainly for testing. The activation is usually done - right before the device is opened. */ - if (ActivateDevice (GPGCEDEV_KEY_NAME, 0) == INVALID_HANDLE_VALUE) - { - fprintf (stderr, PGM": ActivateDevice 1 failed: rc=%d\n", - (int)GetLastError ()); - result = 1; - } - else if (ActivateDevice (GPGCEDEV_KEY_NAME2, 0) == INVALID_HANDLE_VALUE) - { - fprintf (stderr, PGM": ActivateDevice 2 failed: rc=%d\n", - (int)GetLastError ()); - result = 1; - } - else - { - fprintf (stderr, PGM": devices activated\n"); - hd = CreateFile (L"GPG1:", GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if (hd == INVALID_HANDLE_VALUE) - { - fprintf (stderr, PGM": opening `GPG1:' failed: rc=%d\n", - (int)GetLastError ()); - result = 1; - } - else - { - fprintf (stderr, PGM": device `GPG1:' seems to work\n"); - CloseHandle (hd); - } - - hd = CreateFile (L"GPG2:", GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if (hd == INVALID_HANDLE_VALUE) - { - fprintf (stderr, PGM": opening `GPG2:' failed: rc=%d\n", - (int)GetLastError ()); - result = 1; - } - else - { - fprintf (stderr, PGM": device `GPG2:' seems to work\n"); - CloseHandle (hd); - } - - } - } - else if (argc > 1 && !strcmp (argv[1], "--gravity")) - result = gravity (); - /* else if (argc > 1 && !strcmp (argv[1], "--gps")) */ - /* result = gps (); */ - else if (argc > 1 && !strcmp (argv[1], "--log")) - { - HANDLE hd; - - hd = CreateFile (L"GPG2:", GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if (hd == INVALID_HANDLE_VALUE) - { - fprintf (stderr, PGM": opening `GPG2:' failed: rc=%d\n", - (int)GetLastError ()); - result = 1; - } - else - { - char marktwain[] = "I have never let my schooling interfere" - " with my education.\n"; - DWORD nwritten; - int i; - - for (i=0; i < 3; i++) - { - if (!WriteFile (hd, marktwain, strlen (marktwain), - &nwritten, NULL)) - { - fprintf (stderr, PGM": writing `GPG2:' failed: rc=%d\n", - (int)GetLastError ()); - result = 1; - } - Sleep (200); - } - CloseHandle (hd); - } - } - else if (argc > 1 && !strcmp (argv[1], "--enable-debug")) - result = enable_debug (1); - else if (argc > 1 && !strcmp (argv[1], "--disable-debug")) - result = enable_debug (0); - else if (argc > 1 && !strcmp (argv[1], "--enable-log")) - result = enable_log (1); - else if (argc > 1 && !strcmp (argv[1], "--disable-log")) - result = enable_log (0); - else if (argc > 1 && !strcmp (argv[1], "--gpgme-log")) - set_show_registry (L"Software\\GNU\\gpgme", L"debug", - argc > 2? argv[2] : NULL); - else if (argc > 1 && !strcmp (argv[1], "--gnupg-log")) - set_show_registry (L"Software\\GNU\\GnuPG", L"DefaultLogFile", - argc > 2? argv[2] : NULL); - else - { - fprintf (stderr, - "usage: " PGM " COMMAND\n" - "Commands are:\n" - " --register Register the GPGCEDEV device\n" - " --deactivate Deactivate the GPGCEDEV device\n" - " --activate Activate the GPGCEDEV devive\n" - " --enable-debug Enable debugging of GPGCEDEV device\n" - " --disable-debug Disable debugging of GPGCEDEV device\n" - " --gravity Show output of the gravity sensor\n" - " --enable-log Enable logging via \"GPG2:\"\n" - " --disable-log Disable logging via \"GPG2:\"\n" - " --log Write a test string to \"GPG2:\"\n" - " --gpgme-log [ARG] Show or set GPGME log output\n" - " --gnupg-log [ARG] Show or set GnuPG default log file\n" - " (No ARG shows, \"none\" disables)\n" - ); - result = 1; - } - - fflush (stdout); - fflush (stderr); - Sleep (1000); - return result; -} - - diff --git a/src/setenv.c b/src/setenv.c index 3410b30..487de4e 100644 --- a/src/setenv.c +++ b/src/setenv.c @@ -21,8 +21,6 @@ # include #endif -#ifndef HAVE_W32CE_SYSTEM - #define setenv _assuan_setenv #define unsetenv _assuan_unsetenv #define clearenv _assuan_clearenv @@ -354,5 +352,3 @@ weak_alias (__setenv, setenv) weak_alias (__unsetenv, unsetenv) weak_alias (__clearenv, clearenv) #endif - -#endif /*!HAVE_W32CE_SYSTEM*/ diff --git a/src/system-w32ce.c b/src/system-w32ce.c deleted file mode 100644 index da5dcf2..0000000 --- a/src/system-w32ce.c +++ /dev/null @@ -1,706 +0,0 @@ -/* system-w32ce.c - System support functions for WindowsCE. - * Copyright (C) 2010 Free Software Foundation, Inc. - * - * This file is part of Assuan. - * - * Assuan is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * Assuan 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see . - * SPDX-License-Identifier: LGPL-2.1+ - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -# ifdef HAVE_WINSOCK2_H -# include -# endif -#include -#include -#include - -#include "assuan-defs.h" -#include "debug.h" - - -#define GPGCEDEV_IOCTL_GET_RVID \ - CTL_CODE (FILE_DEVICE_STREAMS, 2048, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define GPGCEDEV_IOCTL_MAKE_PIPE \ - CTL_CODE (FILE_DEVICE_STREAMS, 2049, METHOD_BUFFERED, FILE_ANY_ACCESS) - - - - -static wchar_t * -utf8_to_wchar (const char *string) -{ - int n; - size_t nbytes; - wchar_t *result; - - if (!string) - return NULL; - - n = MultiByteToWideChar (CP_UTF8, 0, string, -1, NULL, 0); - if (n < 0) - { - gpg_err_set_errno (EINVAL); - return NULL; - } - - nbytes = (size_t)(n+1) * sizeof(*result); - if (nbytes / sizeof(*result) != (n+1)) - { - gpg_err_set_errno (ENOMEM); - return NULL; - } - result = malloc (nbytes); - if (!result) - return NULL; - - n = MultiByteToWideChar (CP_UTF8, 0, string, -1, result, n); - if (n < 0) - { - free (result); - gpg_err_set_errno (EINVAL); - result = NULL; - } - return result; -} - -/* Convenience function. */ -static void -free_wchar (wchar_t *string) -{ - if (string) - free (string); -} - - - -assuan_fd_t -assuan_fdopen (int fd) -{ - return (assuan_fd_t)fd; -} - - - -/* Sleep for the given number of microseconds. Default - implementation. */ -void -__assuan_usleep (assuan_context_t ctx, unsigned int usec) -{ - if (usec) - Sleep (usec / 1000); -} - - - -/* Prepare a pipe. Returns a handle which is, depending on WRITE_END, - will either act the read or as the write end of the pipe. The - other value returned is a rendezvous id used to complete the pipe - creation with _assuan_w32ce_finish_pipe. The rendezvous id may be - passed to another process and that process may finish the pipe - creation. This creates the interprocess pipe. The rendezvous id - is not a handle but a plain number; there is no release function - and care should be taken not to pass it to a function expecting a - handle. */ -HANDLE -_assuan_w32ce_prepare_pipe (int *r_rvid, int write_end) -{ - HANDLE hd; - LONG rvid; - - ActivateDevice (L"Drivers\\GnuPG_Device", 0); - - /* Note: Using "\\$device\\GPG1" should be identical to "GPG1:". - However this returns an invalid parameter error without having - called GPG_Init in the driver. The docs mention something about - RegisterAFXEx but that API is not documented. */ - hd = CreateFile (L"GPG1:", write_end? GENERIC_WRITE : GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if (hd != INVALID_HANDLE_VALUE) - { - if (!DeviceIoControl (hd, GPGCEDEV_IOCTL_GET_RVID, - NULL, 0, &rvid, sizeof rvid, NULL, NULL)) - { - DWORD lastrc = GetLastError (); - CloseHandle (hd); - hd = INVALID_HANDLE_VALUE; - SetLastError (lastrc); - } - else - *r_rvid = rvid; - } - - return hd; -} - - -/* Create a pipe. WRITE_END shall have the opposite value of the one - pssed to _assuan_w32ce_prepare_pipe; see there for more - details. */ -HANDLE -_assuan_w32ce_finish_pipe (int rvid, int write_end) -{ - HANDLE hd; - - if (!rvid) - { - SetLastError (ERROR_INVALID_HANDLE); - return INVALID_HANDLE_VALUE; - } - - hd = CreateFile (L"GPG1:", write_end? GENERIC_WRITE : GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,NULL); - if (hd != INVALID_HANDLE_VALUE) - { - if (!DeviceIoControl (hd, GPGCEDEV_IOCTL_MAKE_PIPE, - &rvid, sizeof rvid, NULL, 0, NULL, NULL)) - { - DWORD lastrc = GetLastError (); - CloseHandle (hd); - hd = INVALID_HANDLE_VALUE; - SetLastError (lastrc); - } - } - - return hd; -} - - -/* WindowsCE does not provide a pipe feature. However we need - something like a pipe to convey data between processes and in some - cases within a process. This replacement is not only used by - libassuan but exported and thus usable by gnupg and gpgme as well. */ -DWORD -_assuan_w32ce_create_pipe (HANDLE *read_hd, HANDLE *write_hd, - LPSECURITY_ATTRIBUTES sec_attr, DWORD size) -{ - HANDLE hd[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}; - int rvid; - int rc = 0; - - hd[0] = _assuan_w32ce_prepare_pipe (&rvid, 0); - if (hd[0] != INVALID_HANDLE_VALUE) - { - hd[1] = _assuan_w32ce_finish_pipe (rvid, 1); - if (hd[1] != INVALID_HANDLE_VALUE) - rc = 1; - else - { - DWORD lastrc = GetLastError (); - CloseHandle (hd[0]); - hd[0] = INVALID_HANDLE_VALUE; - SetLastError (lastrc); - } - } - - *read_hd = hd[0]; - *write_hd = hd[1]; - return rc; -} - - -/* Create a pipe with one inheritable end. Default implementation. - If INHERIT_IDX is 0, the read end of the pipe is made inheritable; - with INHERIT_IDX is 1 the write end will be inheritable. The - question now is how we create an inheritable pipe end under windows - CE were handles are process local objects? The trick we employ is - to defer the actual creation to the other end: We create an - incomplete pipe and pass a rendezvous id to the other end - (process). The other end now uses the rendezvous id to lookup the - pipe in our device driver, creates a new handle and uses that one - to finally establish the pipe. */ -int -__assuan_pipe (assuan_context_t ctx, assuan_fd_t fd[2], int inherit_idx) -{ - HANDLE hd; - int rvid; - - hd = _assuan_w32ce_prepare_pipe (&rvid, !inherit_idx); - if (hd == INVALID_HANDLE_VALUE) - { - TRACE1 (ctx, ASSUAN_LOG_SYSIO, "__assuan_pipe", ctx, - "CreatePipe failed: %s", _assuan_w32_strerror (ctx, -1)); - gpg_err_set_errno (EIO); - return -1; - } - - if (inherit_idx) - { - fd[0] = hd; - fd[1] = (void*)rvid; - } - else - { - fd[0] = (void*)rvid; - fd[1] = hd; - } - return 0; -} - - - -/* Close the given file descriptor, created with _assuan_pipe or one - of the socket functions. Default implementation. */ -int -__assuan_close (assuan_context_t ctx, assuan_fd_t fd) -{ - int rc = closesocket (HANDLE2SOCKET(fd)); - int err = WSAGetLastError (); - - /* Note that gpg_err_set_errno on Windows CE overwrites - WSAGetLastError() (via SetLastError()). */ - if (rc) - gpg_err_set_errno (_assuan_sock_wsa2errno (err)); - if (rc && err == WSAENOTSOCK) - { - rc = CloseHandle (fd); - if (rc) - /* FIXME. */ - gpg_err_set_errno (EIO); - } - return rc; -} - - - -ssize_t -__assuan_read (assuan_context_t ctx, assuan_fd_t fd, void *buffer, size_t size) -{ - /* Due to the peculiarities of the W32 API we can't use read for a - network socket and thus we try to use recv first and fallback to - read if recv detects that it is not a network socket. */ - int res; - - TRACE_BEG3 (ctx, ASSUAN_LOG_SYSIO, "__assuan_read", ctx, - "fd=0x%x, buffer=%p, size=%i", fd, buffer, size); - -#ifdef HAVE_W32CE_SYSTEM - /* This is a bit of a hack to support stdin over ssh. Note that - fread buffers fully while getchar is line buffered. Weird, but - that's the way it is. ASSUAN_STDIN and ASSUAN_STDOUT are - special handle values that shouldn't occur in the wild. */ - if (fd == ASSUAN_STDIN) - { - int i = 0; - int chr; - while (i < size) - { - chr = getchar(); - if (chr == EOF) - break; - ((char*)buffer)[i++] = (char) chr; - if (chr == '\n') - break; - } - return TRACE_SYSRES (i); - } -#endif - - res = recv (HANDLE2SOCKET (fd), buffer, size, 0); - if (res == -1) - { - TRACE_LOG1 ("recv failed: rc=%d", (int)WSAGetLastError ()); - switch (WSAGetLastError ()) - { - case WSAENOTSOCK: - { - DWORD nread = 0; - - res = ReadFile (fd, buffer, size, &nread, NULL); - if (! res) - { - TRACE_LOG1 ("ReadFile failed: rc=%d", (int)GetLastError ()); - switch (GetLastError ()) - { - case ERROR_BROKEN_PIPE: - gpg_err_set_errno (EPIPE); - break; - - case ERROR_PIPE_NOT_CONNECTED: - case ERROR_BUSY: - gpg_err_set_errno (EAGAIN); - break; - - default: - gpg_err_set_errno (EIO); - } - res = -1; - } - else - res = (int) nread; - } - break; - - case WSAEWOULDBLOCK: - gpg_err_set_errno (EAGAIN); - break; - - case ERROR_BROKEN_PIPE: - gpg_err_set_errno (EPIPE); - break; - - default: - gpg_err_set_errno (EIO); - break; - } - } - return TRACE_SYSRES (res); -} - - - -ssize_t -__assuan_write (assuan_context_t ctx, assuan_fd_t fd, const void *buffer, - size_t size) -{ - /* Due to the peculiarities of the W32 API we can't use write for a - network socket and thus we try to use send first and fallback to - write if send detects that it is not a network socket. */ - int res; - - TRACE_BEG3 (ctx, ASSUAN_LOG_SYSIO, "__assuan_write", ctx, - "fd=0x%x, buffer=%p, size=%i", fd, buffer, size); - -#ifdef HAVE_W32CE_SYSTEM - /* This is a bit of a hack to support stdout over ssh. Note that - fread buffers fully while getchar is line buffered. Weird, but - that's the way it is. ASSUAN_STDIN and ASSUAN_STDOUT are - special handle values that shouldn't occur in the wild. */ - if (fd == ASSUAN_STDOUT) - { - res = fwrite (buffer, 1, size, stdout); - return TRACE_SYSRES (res); - } -#endif - - res = send ((int)fd, buffer, size, 0); - if (res == -1 && WSAGetLastError () == WSAENOTSOCK) - { - DWORD nwrite; - - TRACE_LOG ("send call failed - trying WriteFile"); - res = WriteFile (fd, buffer, size, &nwrite, NULL); - if (! res) - { - TRACE_LOG1 ("WriteFile failed: rc=%d", (int)GetLastError ()); - switch (GetLastError ()) - { - case ERROR_BROKEN_PIPE: - case ERROR_NO_DATA: - gpg_err_set_errno (EPIPE); - break; - - case ERROR_PIPE_NOT_CONNECTED: - case ERROR_BUSY: - gpg_err_set_errno (EAGAIN); - break; - - default: - gpg_err_set_errno (EIO); - break; - } - res = -1; - } - else - res = (int) nwrite; - } - else if (res == -1) - TRACE_LOG1 ("send call failed: rc=%d", (int)GetLastError ()); - return TRACE_SYSRES (res); -} - - - -int -__assuan_recvmsg (assuan_context_t ctx, assuan_fd_t fd, assuan_msghdr_t msg, - int flags) -{ - gpg_err_set_errno (ENOSYS); - return -1; -} - - - - -int -__assuan_sendmsg (assuan_context_t ctx, assuan_fd_t fd, assuan_msghdr_t msg, - int flags) -{ - gpg_err_set_errno (ENOSYS); - return -1; -} - - - - -/* Build a command line for use with W32's CreateProcess. On success - CMDLINE gets the address of a newly allocated string. */ -static int -build_w32_commandline (assuan_context_t ctx, const char * const *argv, - assuan_fd_t fd0, assuan_fd_t fd1, assuan_fd_t fd2, - int fd2_isnull, - char **cmdline) -{ - int i, n; - const char *s; - char *buf, *p; - char fdbuf[3*30]; - - p = fdbuf; - *p = 0; - if (fd0 != ASSUAN_INVALID_FD) - { - snprintf (p, 25, "-&S0=%d ", (int)fd0); - p += strlen (p); - } - if (fd1 != ASSUAN_INVALID_FD) - { - snprintf (p, 25, "-&S1=%d ", (int)fd1); - p += strlen (p); - } - if (fd2 != ASSUAN_INVALID_FD) - { - if (fd2_isnull) - strcpy (p, "-&S2=null "); - else - snprintf (p, 25, "-&S2=%d ", (int)fd2); - p += strlen (p); - } - - *cmdline = NULL; - n = strlen (fdbuf); - for (i=0; (s = argv[i]); i++) - { - if (!i) - continue; /* Ignore argv[0]. */ - n += strlen (s) + 1 + 2; /* (1 space, 2 quoting) */ - for (; *s; s++) - if (*s == '\"') - n++; /* Need to double inner quotes. */ - } - n++; - - buf = p = _assuan_malloc (ctx, n); - if (! buf) - return -1; - - p = stpcpy (p, fdbuf); - for (i = 0; argv[i]; i++) - { - if (!i) - continue; /* Ignore argv[0]. */ - if (i > 1) - p = stpcpy (p, " "); - - if (! *argv[i]) /* Empty string. */ - p = stpcpy (p, "\"\""); - else if (strpbrk (argv[i], " \t\n\v\f\"")) - { - p = stpcpy (p, "\""); - for (s = argv[i]; *s; s++) - { - *p++ = *s; - if (*s == '\"') - *p++ = *s; - } - *p++ = '\"'; - *p = 0; - } - else - p = stpcpy (p, argv[i]); - } - - *cmdline = buf; - return 0; -} - - -int -__assuan_spawn (assuan_context_t ctx, pid_t *r_pid, const char *name, - const char **argv, - assuan_fd_t fd_in, assuan_fd_t fd_out, - assuan_fd_t *fd_child_list, - void (*atfork) (void *opaque, int reserved), - void *atforkvalue, unsigned int flags) -{ - PROCESS_INFORMATION pi = - { - NULL, /* Returns process handle. */ - 0, /* Returns primary thread handle. */ - 0, /* Returns pid. */ - 0 /* Returns tid. */ - }; - assuan_fd_t fd; - assuan_fd_t *fdp; - assuan_fd_t fd_err; - int fd_err_isnull = 0; - char *cmdline; - - /* Dup stderr to /dev/null unless it is in the list of FDs to be - passed to the child. Well we don't actually open nul because - that is not available on Windows, but use our hack for it. - Because an RVID of 0 is an invalid value and HANDLES will never - have this value either, we test for this as well. */ - - /* FIXME: As long as we can't decide whether a handle is a real - handler or an rendezvous id we can't do anything with the - FD_CHILD_LIST. We can't do much with stderr either, thus we - better don't pass stderr to the child at all. If we would do so - and it is not a rendezvous id the client would run into - problems. */ - fd = assuan_fd_from_posix_fd (fileno (stderr)); - fdp = fd_child_list; - if (fdp) - { - for (; *fdp != ASSUAN_INVALID_FD && *fdp != 0 && *fdp != fd; fdp++) - ; - } - if (!fdp || *fdp == ASSUAN_INVALID_FD) - fd_err_isnull = 1; - fd_err = ASSUAN_INVALID_FD; - - if (build_w32_commandline (ctx, argv, fd_in, fd_out, fd_err, fd_err_isnull, - &cmdline)) - { - return -1; - } - - TRACE2 (ctx, ASSUAN_LOG_SYSIO, "__assuan_spawn", ctx, - "path=`%s' cmdline=`%s'", name, cmdline); - - { - wchar_t *wcmdline, *wname; - - wcmdline = utf8_to_wchar (cmdline); - _assuan_free (ctx, cmdline); - if (!wcmdline) - return -1; - - wname = utf8_to_wchar (name); - if (!wname) - { - free_wchar (wcmdline); - return -1; - } - - if (!CreateProcess (wname, /* Program to start. */ - wcmdline, /* Command line arguments. */ - NULL, /* (not supported) */ - NULL, /* (not supported) */ - FALSE, /* (not supported) */ - (CREATE_SUSPENDED), /* Creation flags. */ - NULL, /* (not supported) */ - NULL, /* (not supported) */ - NULL, /* (not supported) */ - &pi /* Returns process information.*/ - )) - { - TRACE1 (ctx, ASSUAN_LOG_SYSIO, "__assuan_spawn", ctx, - "CreateProcess failed: %s", _assuan_w32_strerror (ctx, -1)); - free_wchar (wname); - free_wchar (wcmdline); - gpg_err_set_errno (EIO); - return -1; - } - free_wchar (wname); - free_wchar (wcmdline); - } - - ResumeThread (pi.hThread); - - TRACE4 (ctx, ASSUAN_LOG_SYSIO, "__assuan_spawn", ctx, - "CreateProcess ready: hProcess=%p hThread=%p" - " dwProcessID=%d dwThreadId=%d\n", - pi.hProcess, pi.hThread, (int) pi.dwProcessId, (int) pi.dwThreadId); - - CloseHandle (pi.hThread); - - *r_pid = (pid_t) pi.hProcess; - return 0; -} - - - - -pid_t -__assuan_waitpid (assuan_context_t ctx, pid_t pid, int nowait, - int *status, int options) -{ - CloseHandle ((HANDLE) pid); - return 0; -} - - - -int -__assuan_socketpair (assuan_context_t ctx, int namespace, int style, - int protocol, assuan_fd_t filedes[2]) -{ - gpg_err_set_errno (ENOSYS); - return -1; -} - - -int -__assuan_socket (assuan_context_t ctx, int namespace, int style, int protocol) -{ - int res; - - res = socket (namespace, style, protocol); - if (res == -1) - gpg_err_set_errno (_assuan_sock_wsa2errno (WSAGetLastError ())); - return res; -} - - -int -__assuan_connect (assuan_context_t ctx, int sock, struct sockaddr *addr, - socklen_t length) -{ - int res; - - res = connect (sock, addr, length); - if (res < 0) - gpg_err_set_errno (_assuan_sock_wsa2errno (WSAGetLastError ())); - return res; -} - - - -/* The default system hooks for assuan contexts. */ -struct assuan_system_hooks _assuan_system_hooks = - { - ASSUAN_SYSTEM_HOOKS_VERSION, - __assuan_usleep, - __assuan_pipe, - __assuan_close, - __assuan_read, - __assuan_write, - __assuan_recvmsg, - __assuan_sendmsg, - __assuan_spawn, - __assuan_waitpid, - __assuan_socketpair, - __assuan_socket, - __assuan_connect - }; diff --git a/src/system.c b/src/system.c index fa13987..e5104bb 100644 --- a/src/system.c +++ b/src/system.c @@ -203,9 +203,6 @@ _assuan_close_inheritable (assuan_context_t ctx, assuan_fd_t fd) TRACE1 (ctx, ASSUAN_LOG_SYSIO, "_assuan_close_inheritable", ctx, "fd=0x%x", fd); -#ifdef HAVE_W32CE_SYSTEM - return 0; /* Nothing to do because it is a rendezvous id. */ -#else if (ctx->system.version) return (ctx->system.close) (ctx, fd); else @@ -216,7 +213,6 @@ _assuan_close_inheritable (assuan_context_t ctx, assuan_fd_t fd) _assuan_post_syscall (); return res; } -#endif } diff --git a/src/sysutils.c b/src/sysutils.c index 6c09e47..3778668 100644 --- a/src/sysutils.c +++ b/src/sysutils.c @@ -30,9 +30,6 @@ # include # endif # include -# ifdef HAVE_W32CE_SYSTEM -# include -# endif /*HAVE_W32CE_SYSTEM*/ #endif /*HAVE_W32_SYSTEM*/ #include "assuan-defs.h" @@ -54,87 +51,3 @@ _assuan_sysutils_blurb (void) "\n\n"; return blurb; } - - -/* Return a string from the Win32 Registry or NULL in case of error. - The returned string is allocated using a plain malloc and thus the - caller needs to call the standard free(). The string is looked up - under HKEY_LOCAL_MACHINE. */ -#ifdef HAVE_W32CE_SYSTEM -static char * -w32_read_registry (const wchar_t *dir, const wchar_t *name) -{ - HKEY handle; - DWORD n, nbytes; - wchar_t *buffer = NULL; - char *result = NULL; - - if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &handle)) - return NULL; /* No need for a RegClose, so return immediately. */ - - nbytes = 1; - if (RegQueryValueEx (handle, name, 0, NULL, NULL, &nbytes)) - goto out; - buffer = malloc ((n=nbytes+2)); - if (!buffer) - goto out; - if (RegQueryValueEx (handle, name, 0, NULL, (PBYTE)buffer, &n)) - { - free (buffer); - buffer = NULL; - goto out; - } - - n = WideCharToMultiByte (CP_UTF8, 0, buffer, nbytes, NULL, 0, NULL, NULL); - if (n < 0 || (n+1) <= 0) - goto out; - result = malloc (n+1); - if (!result) - goto out; - n = WideCharToMultiByte (CP_UTF8, 0, buffer, nbytes, result, n, NULL, NULL); - if (n < 0) - { - free (result); - result = NULL; - goto out; - } - result[n] = 0; - - out: - free (buffer); - RegCloseKey (handle); - return result; -} -#endif /*HAVE_W32CE_SYSTEM*/ - - - -#ifdef HAVE_W32CE_SYSTEM -/* Replacement for getenv which takes care of the our use of getenv. - The code is not thread safe but we expect it to work in all cases - because it is called for the first time early enough. */ -char * -_assuan_getenv (const char *name) -{ - static int initialized; - static char *val_debug; - static char *val_full_logging; - - if (!initialized) - { - val_debug = w32_read_registry (L"\\Software\\GNU\\libassuan", - L"debug"); - val_full_logging = w32_read_registry (L"\\Software\\GNU\\libassuan", - L"full_logging"); - initialized = 1; - } - - - if (!strcmp (name, "ASSUAN_DEBUG")) - return val_debug; - else if (!strcmp (name, "ASSUAN_FULL_LOGGING")) - return val_full_logging; - else - return NULL; -} -#endif /*HAVE_W32CE_SYSTEM*/ diff --git a/src/w32ce-add.h b/src/w32ce-add.h deleted file mode 100644 index 1f7d7db..0000000 --- a/src/w32ce-add.h +++ /dev/null @@ -1,34 +0,0 @@ -## w32ce-add.h - Include fragment to build assuan.h. -## Copyright (C) 2010 Free Software Foundation, Inc. -## -## This file is part of Assuan. -## -## Assuan is free software; you can redistribute it and/or modify it -## under the terms of the GNU Lesser General Public License as -## published by the Free Software Foundation; either version 2.1 of -## the License, or (at your option) any later version. -## -## Assuan 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 -## Lesser General Public License for more details. -## -## You should have received a copy of the GNU Lesser General Public -## License along with this program; if not, see . -## SPDX-License-Identifier: LGPL-2.1+ -## -## -## This file is included by the mkheader tool. Lines starting with -## a double hash mark are not copied to the destination file. - -HANDLE _assuan_w32ce_prepare_pipe (int *r_rvid, int write_end); -HANDLE _assuan_w32ce_finish_pipe (int rvid, int write_end); -DWORD _assuan_w32ce_create_pipe (HANDLE *read_hd, HANDLE *write_hd, - LPSECURITY_ATTRIBUTES sec_attr, DWORD size); -#define CreatePipe(a,b,c,d) _assuan_w32ce_create_pipe ((a),(b),(c),(d)) - -/* Magic handle values. Let's hope those never occur legitimately as - handles or sockets. (Sockets are numbered sequentially from 0, - while handles seem aligned to wordsize. */ -#define ASSUAN_STDIN (void*)0x7ffffffd -#define ASSUAN_STDOUT (void*)0x7fffffff diff --git a/src/w32ce-fd-t.inc.h b/src/w32ce-fd-t.inc.h deleted file mode 100644 index 70c7997..0000000 --- a/src/w32ce-fd-t.inc.h +++ /dev/null @@ -1,33 +0,0 @@ -## w32ce-fd-t.inc.h - Include fragment to build assuan.h. -## Copyright (C) 2010 Free Software Foundation, Inc. -## -## This file is part of Assuan. -## -## Assuan is free software; you can redistribute it and/or modify it -## under the terms of the GNU Lesser General Public License as -## published by the Free Software Foundation; either version 2.1 of -## the License, or (at your option) any later version. -## -## Assuan 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 -## Lesser General Public License for more details. -## -## You should have received a copy of the GNU Lesser General Public -## License along with this program; if not, see . -## SPDX-License-Identifier: LGPL-2.1+ -## -## -## This file is included by the mkheader tool. Lines starting with -## a double hash mark are not copied to the destination file. - -typedef void *assuan_fd_t; -#define ASSUAN_INVALID_FD ((void*)(-1)) -#define ASSUAN_INVALID_PID ((pid_t) -1) -static GPG_ERR_INLINE assuan_fd_t -assuan_fd_from_posix_fd (int fd) -{ - return (assuan_fd_t)(fd); -} - -##EOF## diff --git a/tests/Makefile.am b/tests/Makefile.am index b547d37..f43c712 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -20,17 +20,13 @@ TESTS_ENVIRONMENT = -EXTRA_DIST = motd ce-createpipe.c +EXTRA_DIST = motd BUILT_SOURCES = CLEANFILES = TESTS = version -if HAVE_W32CE_SYSTEM -w32cetools = ce-createpipe ce-server -endif - if HAVE_W32_SYSTEM testtools = else diff --git a/tests/ce-createpipe.c b/tests/ce-createpipe.c deleted file mode 100644 index b44784c..0000000 --- a/tests/ce-createpipe.c +++ /dev/null @@ -1,179 +0,0 @@ -/* ce-createpipe.c - Test the W32CE CreatePipe implementation. - Copyright (C) 2010 Free Software Foundation, Inc. - - This file is part of Assuan. - - Assuan is free software; you can redistribute it and/or modify it - under the terms of 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. - - Assuan 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, see . - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include - -#define WIN32_LEAN_AND_MEAN -#include - -#include "common.h" - -#include "../src/assuan.h" /* We need the CreatePipe prototype. */ - - -static DWORD -reader_thread (void *arg) -{ - HANDLE hd = arg; - DWORD nread; - char buffer[16]; - - for (;;) - { - if (!ReadFile (hd, buffer, sizeof buffer, &nread, FALSE)) - { - log_error ("reader: ReadFile failed: rc=%d\n", (int)GetLastError ()); - break; - } - log_info ("reader: read %d bytes\n", (int)nread); - log_printhex ("got: ", buffer, nread); - } - - log_info ("reader: finished\n"); - CloseHandle (hd); - return 0; -} - - -static DWORD -writer_thread (void *arg) -{ - HANDLE hd = arg; - DWORD nwritten; - int i = 0; - int j; - char buffer[20]; - int count; - - for (count=0; count < 30; count++) - { - for (j=0; j < sizeof buffer; j++) - buffer[j] = i++; - - if (!WriteFile (hd, buffer, sizeof buffer, &nwritten, NULL)) - { - log_error ("writer: WriteFile failed: rc=%d\n", (int)GetLastError ()); - break; - } - if (nwritten != sizeof buffer) - log_info ("writer: wrote only %d bytes\n", (int)nwritten); - } - - log_info ("writer: finished\n"); - CloseHandle (hd); - return 0; -} - - - -static void -run_test (void) -{ - HANDLE hd[2]; - HANDLE threads[2]; - - if (!CreatePipe (&hd[0], &hd[1], NULL, 0)) - { - log_error ("CreatePipe failed: rc=%d\n", (int)GetLastError ()); - return; - } - log_info ("pipe created read=%p write=%p\n", hd[0], hd[1]); - - threads[0] = CreateThread (NULL, 0, reader_thread, hd[0], 0, NULL); - if (!threads[0]) - log_fatal ("error creating reader thread: rc=%d\n", (int)GetLastError ()); - else - log_info ("reader thread created\n"); - threads[1] = CreateThread (NULL, 0, writer_thread, hd[1], 0, NULL); - if (!threads[0]) - log_fatal ("error creating writer thread: rc=%d\n", (int)GetLastError ()); - else - log_info ("writer thread created\n"); - - switch (WaitForMultipleObjects (2, threads, FALSE, INFINITE)) - { - case WAIT_OBJECT_0: - log_info ("reader thread finished first\n"); - break; - case WAIT_OBJECT_0 + 1: - log_info ("writer thread finished first\n"); - break; - default: - log_error ("WFMO failed: rc=%d\n", (int)GetLastError ()); - break; - } - - - - CloseHandle (threads[0]); - CloseHandle (threads[1]); -} - - - -/* - M A I N - */ -int -main (int argc, char **argv) -{ - int last_argc = -1; - - if (argc) - { - log_set_prefix (*argv); - argc--; argv++; - } - while (argc && last_argc != argc ) - { - last_argc = argc; - if (!strcmp (*argv, "--help")) - { - printf ("usage: %s [options]\n" - "\n" - "Options:\n" - " --verbose Show what is going on\n", - log_get_prefix ()); - exit (0); - } - if (!strcmp (*argv, "--verbose")) - { - verbose = 1; - argc--; argv++; - } - else if (!strcmp (*argv, "--debug")) - { - verbose = debug = 1; - argc--; argv++; - } - } - - run_test (); - - return errorcount ? 1 : 0; -} - diff --git a/tests/ce-server.c b/tests/ce-server.c deleted file mode 100644 index 0565aee..0000000 --- a/tests/ce-server.c +++ /dev/null @@ -1,1418 +0,0 @@ -/* ce-server.c - An Assuan testbed for W32CE; server code - Copyright (C) 2010 Free Software Foundation, Inc. - - This file is part of Assuan. - - Assuan is free software; you can redistribute it and/or modify it - under the terms of 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. - - Assuan 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, see . - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#ifdef HAVE_W32_SYSTEM -# define WIN32_LEAN_AND_MEAN -# include -#else -# include -# include -# include -# include -# ifdef HAVE_SYS_SELECT_H -# include -# endif -#endif -#include - -#ifdef HAVE_W32CE_SYSTEM -# ifndef FILE_ATTRIBUTE_ROMSTATICREF -# define FILE_ATTRIBUTE_ROMSTATICREF FILE_ATTRIBUTE_OFFLINE -# endif -extern BOOL GetStdioPathW (int, wchar_t *, DWORD *); -extern BOOL SetStdioPathW (int, const wchar_t *); -#endif /*!HAVE_W32CE_SYSTEM*/ - -#include "../src/assuan.h" - -#include "common.h" - -/* The port we are using by default. */ -static short server_port = 15898; - -/* Flag set to indicate a shutdown. */ -static int shutdown_pending; - -/* An object to keep track of file descriptors. */ -struct fdinfo_s -{ - struct fdinfo_s *next; - assuan_fd_t fd; /* The descriptor. */ -}; -typedef struct fdinfo_s *fdinfo_t; - - -/* The local state of a connection. */ -struct state_s -{ - /* The current working directory - access using get_cwd(). */ - char *cwd; - - /* If valid, a socket in listening state created by the dataport - command. */ - assuan_fd_t dataport_listen_fd; - - /* If valid the socket accepted for the dataport. */ - assuan_fd_t dataport_accepted_fd; - - /* The error code from a dataport accept operation. */ - gpg_error_t dataport_accept_err; - - /* A list of all unused descriptors created by dataport commands. */ - fdinfo_t dataport_fds; - - /* The descriptor set by the DATAPORT command. */ - assuan_fd_t dataport_fd; -}; -typedef struct state_s *state_t; - - - -/* Local prototypes. */ -static gpg_error_t cmd_newdataport_cont (void *opaque, gpg_error_t err, - unsigned char *data, size_t datalen); - - - -/* A wrapper around read to make it work under Windows with HANDLES - and socket descriptors. Takes care of EINTR on POSIX. */ -static int -my_read (assuan_fd_t fd, void *buffer, size_t size) -{ - int res; - -#ifdef HAVE_W32_SYSTEM - res = recv (HANDLE2SOCKET (fd), buffer, size, 0); - if (res == -1) - { - switch (WSAGetLastError ()) - { - case WSAENOTSOCK: - { - DWORD nread = 0; - - res = ReadFile (fd, buffer, size, &nread, NULL); - if (!res) - { - switch (GetLastError ()) - { - case ERROR_BROKEN_PIPE: - gpg_err_set_errno (EPIPE); - break; - - default: - gpg_err_set_errno (EIO); - } - res = -1; - } - else - res = (int) nread; - } - break; - - case WSAEWOULDBLOCK: - gpg_err_set_errno (EAGAIN); - break; - - case ERROR_BROKEN_PIPE: - gpg_err_set_errno (EPIPE); - break; - - default: - gpg_err_set_errno (EIO); - break; - } - } - return res; -#else /*!HAVE_W32_SYSTEM*/ - do - res = read (fd, buffer, size); - while (res == -1 && errno == EINTR); - return res; -#endif /*!HAVE_W32_SYSTEM*/ -} - - -/* Extended version of write(2) to guarantee that all bytes are - written. Returns 0 on success or -1 and ERRNO on failure. NOTE: - This function does not return the number of bytes written, so any - error must be treated as fatal for this connection as the state of - the receiver is unknown. This works best if blocking is allowed - (so EAGAIN cannot occur). Under Windows this function handles - socket descriptors and system handles. */ -static int -my_writen (assuan_fd_t fd, const char *buffer, size_t length) -{ - while (length) - { - int nwritten; -#ifdef HAVE_W32_SYSTEM - nwritten = send (HANDLE2SOCKET (fd), buffer, length, 0); - if (nwritten == -1 && WSAGetLastError () == WSAENOTSOCK) - { - DWORD nwrite; - - nwritten = WriteFile (fd, buffer, length, &nwrite, NULL); - if (!nwritten) - { - switch (GetLastError ()) - { - case ERROR_BROKEN_PIPE: - case ERROR_NO_DATA: - gpg_err_set_errno (EPIPE); - break; - - default: - gpg_err_set_errno (EIO); - break; - } - nwritten= -1; - } - else - nwritten = (int)nwrite; - } -#else /*!HAVE_W32_SYSTEM*/ - nwritten = write (fd, buffer, length); -#endif /*!HAVE_W32_SYSTEM*/ - if (nwritten < 0) - { - if (errno == EINTR) - continue; - return -1; /* write error */ - } - length -= nwritten; - buffer += nwritten; - } - return 0; /* okay */ -} - - - -static state_t -new_state (void) -{ - state_t state = xcalloc (1, sizeof *state); - state->dataport_listen_fd = ASSUAN_INVALID_FD; - state->dataport_accepted_fd = ASSUAN_INVALID_FD; - state->dataport_fd = ASSUAN_INVALID_FD; - return state; -} - -static void -release_state (state_t state) -{ - fdinfo_t fi, fi2; - - if (!state) - return; - - xfree (state->cwd); - - if (state->dataport_fd != ASSUAN_INVALID_FD) - assuan_sock_close (state->dataport_fd); - if (state->dataport_listen_fd != ASSUAN_INVALID_FD) - assuan_sock_close (state->dataport_listen_fd); - if (state->dataport_accepted_fd != ASSUAN_INVALID_FD) - assuan_sock_close (state->dataport_accepted_fd); - - for (fi=state->dataport_fds; fi; fi = fi2) - { - fi2 = fi->next; - if (fi->fd != ASSUAN_INVALID_FD) - assuan_sock_close (fi->fd); - } - - xfree (state); -} - - -/* Helper to print a message while leaving a command and to - acknowledge the command. */ -static gpg_error_t -leave_cmd (assuan_context_t ctx, gpg_error_t err) -{ - if (err) - { - const char *name = assuan_get_command_name (ctx); - if (!name) - name = "?"; - if (gpg_err_source (err) == GPG_ERR_SOURCE_DEFAULT) - log_error ("command '%s' failed: %s\n", name, gpg_strerror (err)); - else - log_error ("command '%s' failed: %s <%s>\n", name, - gpg_strerror (err), gpg_strsource (err)); - } - return assuan_process_done (ctx, err); -} - - -#ifdef HAVE_W32CE_SYSTEM -static char * -wchar_to_utf8 (const wchar_t *string) -{ - int n; - size_t length = wcslen (string); - char *result; - - n = WideCharToMultiByte (CP_UTF8, 0, string, length, NULL, 0, NULL, NULL); - if (n < 0 || (n+1) <= 0) - log_fatal ("WideCharToMultiByte failed\n"); - - result = xmalloc (n+1); - n = WideCharToMultiByte (CP_ACP, 0, string, length, result, n, NULL, NULL); - if (n < 0) - log_fatal ("WideCharToMultiByte failed\n"); - - result[n] = 0; - return result; -} - -static wchar_t * -utf8_to_wchar (const char *string) -{ - int n; - size_t length = strlen (string); - wchar_t *result; - size_t nbytes; - - n = MultiByteToWideChar (CP_UTF8, 0, string, length, NULL, 0); - if (n < 0 || (n+1) <= 0) - log_fatal ("MultiByteToWideChar failed\n"); - - nbytes = (size_t)(n+1) * sizeof(*result); - if (nbytes / sizeof(*result) != (n+1)) - log_fatal ("utf8_to_wchar: integer overflow\n"); - result = xmalloc (nbytes); - n = MultiByteToWideChar (CP_UTF8, 0, string, length, result, n); - if (n < 0) - log_fatal ("MultiByteToWideChar failed\n"); - result[n] = 0; - - return result; -} -#endif /*HAVE_W32CE_SYSTEM*/ - -#ifndef HAVE_W32CE_SYSTEM -static char * -gnu_getcwd (void) -{ - size_t size = 100; - - while (1) - { - char *buffer = xmalloc (size); - if (getcwd (buffer, size) == buffer) - return buffer; - xfree (buffer); - if (errno != ERANGE) - return 0; - size *= 2; - } -} -#endif /*!HAVE_W32CE_SYSTEM*/ - - -/* Return the current working directory. The returned string is valid - as long as STATE->cwd is not changed. */ -static const char * -get_cwd (state_t state) -{ - if (!state->cwd) - { - /* No working directory yet. On WindowsCE make it the module - directory of this process. */ -#ifdef HAVE_W32_SYSTEM - char *p; -#endif -#ifdef HAVE_W32CE_SYSTEM - wchar_t buf[MAX_PATH+1]; - size_t n; - - n = GetModuleFileName (NULL, buf, MAX_PATH); - if (!n) - state->cwd = xstrdup ("/"); - else - { - buf[n] = 0; - state->cwd = wchar_to_utf8 (buf); - p = strrchr (state->cwd, '\\'); - if (p) - *p = 0; - } -#else - state->cwd = gnu_getcwd (); -#endif -#ifdef HAVE_W32_SYSTEM - for (p=state->cwd; *p; p++) - if (*p == '\\') - *p = '/'; -#endif /*HAVE_W32_SYSTEM*/ - } - - return state->cwd; -} - - - -static gpg_error_t -reset_notify (assuan_context_t ctx, char *line) -{ - state_t state = assuan_get_pointer (ctx); - fdinfo_t fi, fi2; - - /* Close all lingering dataport connections. */ - for (fi=state->dataport_fds; fi; fi = fi2) - { - fi2 = fi->next; - if (fi->fd != ASSUAN_INVALID_FD) - assuan_sock_close (fi->fd); - } - state->dataport_fds = NULL; - - return 0; -} - - -static gpg_error_t -input_notify (assuan_context_t ctx, char *line) -{ - state_t state = assuan_get_pointer (ctx); - assuan_fd_t fd = assuan_get_input_fd (ctx); - fdinfo_t fi; - - if (fd != ASSUAN_INVALID_FD) - { - /* The fd is now in use use - remove it from the unused list. */ - for (fi=state->dataport_fds; fi; fi = fi->next) - if (fi->fd == fd) - fi->fd = ASSUAN_INVALID_FD; - } - - return 0; -} - - -static gpg_error_t -output_notify (assuan_context_t ctx, char *line) -{ - state_t state = assuan_get_pointer (ctx); - assuan_fd_t fd = assuan_get_output_fd (ctx); - fdinfo_t fi; - - if (fd != ASSUAN_INVALID_FD) - { - /* The fd is now in use - remove it from the unused list. */ - for (fi=state->dataport_fds; fi; fi = fi->next) - if (fi->fd == fd) - fi->fd = ASSUAN_INVALID_FD; - } - - return 0; -} - - - -static const char hlp_echo[] = - "ECHO \n" - "\n" - "Print LINE as data lines.\n"; -static gpg_error_t -cmd_echo (assuan_context_t ctx, char *line) -{ - gpg_error_t err; - - err = assuan_send_data (ctx, line, strlen (line)); - - return leave_cmd (ctx, err); -} - - - -static const char hlp_cat[] = - "CAT []\n" - "\n" - "Copy the content of FILENAME to the descriptor set by the OUTPUT\n" - "command. If no OUTPUT command has been given, send the content\n" - "using data lines. Without FILENAME take the content from the\n" - "descriptor set by the INPUT command; if a DATAPORT has been set\n" - "this descriptor is used for I/O and the INOPUT/OUTPUT descriptors\n" - "are not touched."; -static gpg_error_t -cmd_cat (assuan_context_t ctx, char *line) -{ - state_t state = assuan_get_pointer (ctx); - gpg_error_t err = 0; - assuan_fd_t fd_in = ASSUAN_INVALID_FD; - assuan_fd_t fd_out = ASSUAN_INVALID_FD; - FILE *fp_in = NULL; - char buf[256]; - size_t nread; - int use_dataport = 0; - - if (*line) - { - fp_in = fopen (line, "rb"); - if (!fp_in) - err = gpg_error_from_syserror (); - else - fd_out = assuan_get_output_fd (ctx); - } - else if (state->dataport_fd != ASSUAN_INVALID_FD) - { - use_dataport = 1; - fd_in = state->dataport_fd; - fd_out = state->dataport_fd; - } - else if ((fd_in = assuan_get_input_fd (ctx)) != ASSUAN_INVALID_FD) - { - /* This FD is actually a socket descriptor. We can't fdopen it - because under Windows we ust use recv(2) instead of read(2). - Note that on POSIX systems there is no difference between - libc file descriptors and socket descriptors. */ - - fd_out = assuan_get_output_fd (ctx); - } - else - err = gpg_error (GPG_ERR_ASS_NO_INPUT); - if (err) - goto leave; - - do - { - if (fp_in) - { - nread = fread (buf, 1, sizeof buf, fp_in); - if (nread < sizeof buf) - { - if (ferror (fp_in)) - err = gpg_error_from_syserror (); - else if (feof (fp_in)) - err = gpg_error (GPG_ERR_EOF); - } - } - else - { - int n; - - nread = 0; - n = my_read (fd_in, buf, sizeof buf); - if (n < 0) - err = gpg_error_from_syserror (); - else if (!n) - err = gpg_error (GPG_ERR_EOF); - else - nread = n; - } - - - if (fd_out != ASSUAN_INVALID_FD) - { - if (nread && my_writen (fd_out, buf, nread)) - err = gpg_error_from_syserror (); - } - else if (nread) - err = assuan_send_data (ctx, buf, nread); - } - while (!err); - if (gpg_err_code (err) == GPG_ERR_EOF) - err = 0; - -leave: - if (fp_in) - fclose (fp_in); - if (use_dataport) - { - if (state->dataport_fd != ASSUAN_INVALID_FD) - { - assuan_sock_close (state->dataport_fd); - state->dataport_fd = ASSUAN_INVALID_FD; - } - } - else - { - assuan_close_input_fd (ctx); - assuan_close_output_fd (ctx); - } - return leave_cmd (ctx, err); -} - - -static const char hlp_pwd[] = - "PWD\n" - "\n" - "Print the curent working directory of this session.\n"; -static gpg_error_t -cmd_pwd (assuan_context_t ctx, char *line) -{ - state_t state = assuan_get_pointer (ctx); - gpg_error_t err; - const char *string; - - string = get_cwd (state); - err = assuan_send_data (ctx, string, strlen (string)); - - return leave_cmd (ctx, err); -} - - -static const char hlp_cd[] = - "CD [dir]\n" - "\n" - "Change the curretn directory of the session.\n"; -static gpg_error_t -cmd_cd (assuan_context_t ctx, char *line) -{ - state_t state = assuan_get_pointer (ctx); - gpg_error_t err = 0; - char *newdir, *p; - - for (p=line; *p; p++) - if (*p == '\\') - *p = '/'; - - if (!*line) - { - xfree (state->cwd); - state->cwd = NULL; - get_cwd (state); - } - else - { - if (*line == '/') - newdir = xstrdup (line); - else - newdir = xstrconcat (get_cwd (state), "/", line, NULL); - - while (strlen(newdir) > 1 && line[strlen(newdir)-1] == '/') - line[strlen(newdir)-1] = 0; - xfree (state->cwd); - state->cwd = newdir; - } - - return leave_cmd (ctx, err); -} - - - - - -#ifdef HAVE_W32CE_SYSTEM -static const char hlp_ls[] = - "LS []\n" - "\n" - "List the files described by PATTERN.\n"; -static gpg_error_t -cmd_ls (assuan_context_t ctx, char *line) -{ - state_t state = assuan_get_pointer (ctx); - gpg_error_t err; - WIN32_FIND_DATA fi; - char buf[500]; - HANDLE hd; - char *p, *fname; - wchar_t *wfname; - - if (!*line) - fname = xstrconcat (get_cwd (state), "/*", NULL); - else if (*line == '/' || *line == '\\') - fname = xstrdup (line); - else - fname = xstrconcat (get_cwd (state), "/", line, NULL); - for (p=fname; *p; p++) - if (*p == '/') - *p = '\\'; - assuan_write_status (ctx, "PATTERN", fname); - wfname = utf8_to_wchar (fname); - xfree (fname); - hd = FindFirstFile (wfname, &fi); - free (wfname); - if (hd == INVALID_HANDLE_VALUE) - { - log_info ("FindFirstFile returned %d\n", GetLastError ()); - err = gpg_error_from_syserror (); /* Works for W32CE. */ - goto leave; - } - - do - { - DWORD attr = fi.dwFileAttributes; - - fname = wchar_to_utf8 (fi.cFileName); - snprintf (buf, sizeof buf, - "%c%c%c%c%c%c%c%c%c%c%c%c%c %7lu%c %s\n", - (attr & FILE_ATTRIBUTE_DIRECTORY) - ? ((attr & FILE_ATTRIBUTE_DEVICE)? 'c':'d'):'-', - (attr & FILE_ATTRIBUTE_READONLY)? 'r':'-', - (attr & FILE_ATTRIBUTE_HIDDEN)? 'h':'-', - (attr & FILE_ATTRIBUTE_SYSTEM)? 's':'-', - (attr & FILE_ATTRIBUTE_ARCHIVE)? 'a':'-', - (attr & FILE_ATTRIBUTE_COMPRESSED)? 'c':'-', - (attr & FILE_ATTRIBUTE_ENCRYPTED)? 'e':'-', - (attr & FILE_ATTRIBUTE_INROM)? 'R':'-', - (attr & FILE_ATTRIBUTE_REPARSE_POINT)? 'P':'-', - (attr & FILE_ATTRIBUTE_ROMMODULE)? 'M':'-', - (attr & FILE_ATTRIBUTE_ROMSTATICREF)? 'R':'-', - (attr & FILE_ATTRIBUTE_SPARSE_FILE)? 'S':'-', - (attr & FILE_ATTRIBUTE_TEMPORARY)? 't':'-', - (unsigned long)fi.nFileSizeLow, - fi.nFileSizeHigh? 'X':' ', - fname); - free (fname); - err = assuan_send_data (ctx, buf, strlen (buf)); - if (!err) - err = assuan_send_data (ctx, NULL, 0); - } - while (!err && FindNextFile (hd, &fi)); - if (err) - ; - else if (GetLastError () == ERROR_NO_MORE_FILES) - err = 0; - else - { - log_info ("FindNextFile returned %d\n", GetLastError ()); - err = gpg_error_from_syserror (); - } - FindClose (hd); - - leave: - return leave_cmd (ctx, err); -} -#endif /*HAVE_W32CE_SYSTEM*/ - - -#ifdef HAVE_W32CE_SYSTEM -static const char hlp_run[] = - "RUN []\n" - "\n" - "Run the program in FILENAME with the arguments ARGS.\n" - "This creates a new process and waits for it to finish.\n" - "FIXME: The process' stdin is connected to the file set by the\n" - "INPUT command; stdout and stderr to the one set by OUTPUT.\n"; -static gpg_error_t -cmd_run (assuan_context_t ctx, char *line) -{ - /* state_t state = assuan_get_pointer (ctx); */ - gpg_error_t err; - BOOL w32ret; - PROCESS_INFORMATION pi = { NULL, 0, 0, 0 }; - char *p; - wchar_t *pgmname = NULL; - wchar_t *cmdline = NULL; - int code; - DWORD exc; - int idx; - struct { - HANDLE hd[2]; - int oldname_valid; - wchar_t oldname[MAX_PATH]; - } pipes[3]; - - for (idx=0; idx < 3; idx++) - { - pipes[idx].hd[0] = pipes[idx].hd[1] = INVALID_HANDLE_VALUE; - pipes[idx].oldname_valid = 0; - } - - p = strchr (line, ' '); - if (p) - { - *p = 0; - pgmname = utf8_to_wchar (line); - for (p++; *p && *p == ' '; p++) - ; - cmdline = utf8_to_wchar (p); - } - else - pgmname = utf8_to_wchar (line); - { - char *tmp1 = wchar_to_utf8 (pgmname); - char *tmp2 = wchar_to_utf8 (cmdline); - log_info ("CreateProcess, path=`%s' cmdline=`%s'\n", tmp1, tmp2); - xfree (tmp2); - xfree (tmp1); - } - - /* Redirect the standard handles. */ - /* Create pipes. */ - for (idx=0; idx < 3; idx++) - { - if (!_assuan_w32ce_create_pipe (&pipes[idx].hd[0], &pipes[idx].hd[1], - NULL, 0)) - { - err = gpg_error_from_syserror (); - log_error ("CreatePipe failed: %d\n", GetLastError ()); - pipes[idx].hd[0] = pipes[idx].hd[1] = INVALID_HANDLE_VALUE; - goto leave; - } - } - - /* Save currently assigned devices. */ - for (idx=0; idx < 3; idx++) - { - DWORD dwlen = MAX_PATH; - if (!GetStdioPathW (idx, pipes[idx].oldname, &dwlen)) - { - err = gpg_error_from_syserror (); - log_error ("GetStdioPath failed: %d\n", GetLastError ()); - goto leave; - } - pipes[idx].oldname_valid = 1; - } - - /* Connect the pipes. */ - { - if (!SetStdioPathW (1, L"\\mystdout.log")) - { - err = gpg_error_from_syserror (); - log_error ("SetStdioPathW(%d) failed: %d\n", idx, GetLastError ()); - goto leave; - } - if (!SetStdioPathW (2, L"\\mystderr.log")) - { - err = gpg_error_from_syserror (); - log_error ("SetStdioPathW(%d) failed: %d\n", idx, GetLastError ()); - goto leave; - } - } - - /* Create the process, restore the devices and check the error. */ - w32ret = CreateProcess (pgmname, /* Program to start. */ - cmdline, /* Command line arguments. */ - NULL, /* Process security. Not used. */ - NULL, /* Thread security. Not used. */ - FALSE, /* Inherit handles. Not used. */ - CREATE_SUSPENDED, /* Creation flags. */ - NULL, /* Environment. Not used. */ - NULL, /* Use current dir. Not used. */ - NULL, /* Startup information. Not used. */ - &pi /* Returns process information. */ - ); - for (idx=0; idx < 3; idx++) - { - if (pipes[idx].oldname_valid) - { - if (!SetStdioPathW (idx, pipes[idx].oldname)) - log_error ("SetStdioPath(%d) failed during restore: %d\n", - idx, GetLastError ()); - else - pipes[idx].oldname_valid = 0; - } - } - if (!w32ret) - { - /* Error checking after restore so that the messages are visible. */ - log_error ("CreateProcess failed: %d\n", GetLastError ()); - err = gpg_error_from_syserror (); - goto leave; - } - - log_info ("CreateProcess ready: hProcess=%p hThread=%p" - " dwProcessID=%d dwThreadId=%d\n", - pi.hProcess, pi.hThread, - (int) pi.dwProcessId, (int) pi.dwThreadId); - - ResumeThread (pi.hThread); - CloseHandle (pi.hThread); - - code = WaitForSingleObject (pi.hProcess, INFINITE); - switch (code) - { - case WAIT_FAILED: - err = gpg_error_from_syserror ();; - log_error ("waiting for process %d to terminate failed: %d\n", - (int)pi.dwProcessId, GetLastError ()); - break; - - case WAIT_OBJECT_0: - if (!GetExitCodeProcess (pi.hProcess, &exc)) - { - err = gpg_error_from_syserror ();; - log_error ("error getting exit code of process %d: %s\n", - (int)pi.dwProcessId, GetLastError () ); - } - else if (exc) - { - log_info ("error running process: exit status %d\n", (int)exc); - err = gpg_error (GPG_ERR_GENERAL); - } - else - { - err = 0; - } - break; - - default: - err = gpg_error_from_syserror ();; - log_error ("WaitForSingleObject returned unexpected " - "code %d for pid %d\n", code, (int)pi.dwProcessId); - break; - } - CloseHandle (pi.hProcess); - - leave: - for (idx=0; idx < 3; idx++) - { - if (pipes[idx].oldname_valid) - { - if (!SetStdioPathW (idx, pipes[idx].oldname)) - log_error ("SetStdioPath(%d) failed during restore: %d\n", - idx, GetLastError ()); - else - pipes[idx].oldname_valid = 0; - } - } - for (idx=0; idx < 3; idx++) - { - if (pipes[idx].hd[0] != INVALID_HANDLE_VALUE) - CloseHandle (pipes[idx].hd[0]); - if (pipes[idx].hd[1] != INVALID_HANDLE_VALUE) - CloseHandle (pipes[idx].hd[1]); - } - xfree (cmdline); - xfree (pgmname); - return leave_cmd (ctx, err); -} -#endif /*HAVE_W32CE_SYSTEM*/ - - - - - -static const char hlp_newdataport[] = - "NEWDATAPORT\n" - "\n" - "Create a new dataport. The server creates a listening socket and\n" - "issues the inquiry:\n" - " INQUIRE CONNECT-TO \n" - "The client is expected to connect to PORT of the server and confirm\n" - "this by sending just an \"END\". In turn the server sends:\n" - " S FDINFO \n" - "With N being the local descriptor for the accepted connection. This\n" - "descriptor may now be used with INPUT or OUTPUT commands."; -struct cmd_dataport_locals -{ - assuan_context_t ctx; - int passthru; - int port; -}; -static gpg_error_t -cmd_newdataport (assuan_context_t ctx, char *line) -{ - state_t state = assuan_get_pointer (ctx); - gpg_error_t err = 0; - struct sockaddr_in addr; - socklen_t addrlen; - struct cmd_dataport_locals *cont; - char inqline[100]; - - cont = xmalloc (sizeof *cont); - cont->ctx = ctx; - cont->passthru = 0; - cont->port = 0; - - if (state->dataport_listen_fd != ASSUAN_INVALID_FD) - { - log_error ("Oops, still listening on a dataport socket\n"); - state->dataport_listen_fd = ASSUAN_INVALID_FD; - } - if (state->dataport_accepted_fd != ASSUAN_INVALID_FD) - { - log_error ("Oops, still holding an accepted dataport socket\n"); - state->dataport_accepted_fd = ASSUAN_INVALID_FD; - } - state->dataport_accept_err = 0; - - state->dataport_listen_fd = assuan_sock_new (PF_INET, SOCK_STREAM, 0); - if (state->dataport_listen_fd == ASSUAN_INVALID_FD) - { - err = gpg_error_from_syserror (); - log_error ("socket() failed: %s\n", strerror (errno)); - goto leave; - } - - addr.sin_family = AF_INET; - addr.sin_port = 0; - addr.sin_addr.s_addr = htonl (INADDR_ANY); - if (assuan_sock_bind (state->dataport_listen_fd, - (struct sockaddr *)&addr, sizeof addr)) - { - err = gpg_error_from_syserror (); - log_error ("listen() failed: %s\n", strerror (errno)); - goto leave; - } - - if (listen (HANDLE2SOCKET (state->dataport_listen_fd), 1)) - { - err = gpg_error_from_syserror (); - log_error ("listen() failed: %s\n", strerror (errno)); - goto leave; - } - - addrlen = sizeof addr; - if (getsockname (HANDLE2SOCKET (state->dataport_listen_fd), - (struct sockaddr *)&addr, &addrlen)) - { - err = gpg_error_from_syserror (); - log_error ("getsockname() failed: %s\n", strerror (errno)); - goto leave; - } - cont->port = ntohs (addr.sin_port); - - if (verbose) - log_info ("server now also listening on port %d\n", cont->port); - snprintf (inqline, sizeof inqline, "CONNECT-TO %d", cont->port); - err = assuan_inquire_ext (ctx, inqline, 0, cmd_newdataport_cont, cont); - if (!err) - return 0; /* Transfer to continuation. */ - - leave: - cont->passthru = 1; - return cmd_newdataport_cont (cont, err, NULL, 0); -} - -/* Continuation used by cmd_newdataport. */ -static gpg_error_t -cmd_newdataport_cont (void *opaque, gpg_error_t err, - unsigned char *data, size_t datalen) -{ - struct cmd_dataport_locals *cont = opaque; - assuan_context_t ctx = cont->ctx; - state_t state = assuan_get_pointer (ctx); - char numbuf[35]; - fdinfo_t fi; - - if (cont->passthru || err) - goto leave; - - err = state->dataport_accept_err; - if (err) - goto leave; - if (state->dataport_listen_fd != ASSUAN_INVALID_FD - || state->dataport_accepted_fd == ASSUAN_INVALID_FD) - { - err = gpg_error (GPG_ERR_MISSING_ACTION); - goto leave; - } - - for (fi = state->dataport_fds; fi; fi = fi->next) - if (fi->fd == ASSUAN_INVALID_FD) - break; - if (!fi) - { - fi = xcalloc (1, sizeof *fi); - fi->next = state->dataport_fds; - state->dataport_fds = fi; - } - fi->fd = state->dataport_accepted_fd; - state->dataport_accepted_fd = ASSUAN_INVALID_FD; - - /* Note that under Windows the FD is the socket descriptor. Socket - descriptors are neither handles nor libc file descriptors. */ - snprintf (numbuf, sizeof numbuf, "%d", HANDLE2SOCKET (fi->fd)); - err = assuan_write_status (ctx, "FDINFO", numbuf); - - leave: - if (state->dataport_listen_fd != ASSUAN_INVALID_FD) - { - assuan_sock_close (state->dataport_listen_fd); - state->dataport_listen_fd = ASSUAN_INVALID_FD; - } - if (state->dataport_accepted_fd != ASSUAN_INVALID_FD) - { - assuan_sock_close (state->dataport_accepted_fd); - state->dataport_accepted_fd = ASSUAN_INVALID_FD; - } - xfree (cont); - return leave_cmd (ctx, err); -} - - - -static const char hlp_dataport[] = - "DATAPORT FD[=]\n" - "\n" - "Set the file descriptor to read and write data via port.\n" - "This is similar to the \"INPUT\" and \"OUTPUT\" commands\n" - "but useful for socketpairs."; -static gpg_error_t -cmd_dataport (assuan_context_t ctx, char *line) -{ - state_t state = assuan_get_pointer (ctx); - gpg_error_t err; - assuan_fd_t fd; - - if (state->dataport_fd != ASSUAN_INVALID_FD) - { - assuan_sock_close (state->dataport_fd); - state->dataport_fd = ASSUAN_INVALID_FD; - } - - err = assuan_command_parse_fd (ctx, line, &fd); - if (!err && fd != ASSUAN_INVALID_FD) - { - fdinfo_t fi; - - state->dataport_fd = fd; - - /* The fd is now in use use - remove it from the unused list. */ - for (fi=state->dataport_fds; fi; fi = fi->next) - if (fi->fd == fd) - fi->fd = ASSUAN_INVALID_FD; - } - - return leave_cmd (ctx, err); -} - - - -static const char hlp_getinfo[] = - "GETINFO \n" - "\n" - "Multipurpose function to return a variety of information.\n" - "Supported values for WHAT are:\n" - "\n" - " version - Return the version of the program.\n" - " pid - Return the process id of the server.\n" - " dataports - Return a list of usused dataports."; -static gpg_error_t -cmd_getinfo (assuan_context_t ctx, char *line) -{ - state_t state = assuan_get_pointer (ctx); - gpg_error_t err = 0; - char numbuf[50]; - - if (!strcmp (line, "version")) - { - const char *s = VERSION; - err = assuan_send_data (ctx, s, strlen (s)); - } - else if (!strcmp (line, "pid")) - { - snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ()); - err = assuan_send_data (ctx, numbuf, strlen (numbuf)); - } - else if (!strcmp (line, "dataports")) - { - fdinfo_t fi; - int any = 0; - - for (fi=state->dataport_fds; !err && fi; fi = fi->next) - { - if (fi->fd != ASSUAN_INVALID_FD) - { - snprintf (numbuf, sizeof numbuf, "%s%d", - any? " ":"", HANDLE2SOCKET (fi->fd)); - any = 1; - err = assuan_send_data (ctx, numbuf, strlen (numbuf)); - } - } - } - else - err = gpg_error (GPG_ERR_ASS_PARAMETER); - - return leave_cmd (ctx, err); -} - - - -static const char hlp_shutdown[] = - "SHUTDOWN\n" - "\n" - "Shutdown the server process\n"; -static gpg_error_t -cmd_shutdown (assuan_context_t ctx, char *line) -{ - (void)line; - shutdown_pending = 1; - return leave_cmd (ctx, 0);; -} - - -static gpg_error_t -register_commands (assuan_context_t ctx) -{ - static struct - { - const char *name; - gpg_error_t (*handler) (assuan_context_t, char *line); - const char * const help; - } table[] = - { -#ifdef HAVE_W32CE_SYSTEM - { "LS", cmd_ls, hlp_ls }, - { "RUN", cmd_run, hlp_run }, -#endif - { "PWD", cmd_pwd, hlp_pwd }, - { "CD", cmd_cd, hlp_cd }, - { "ECHO", cmd_echo, hlp_echo }, - { "CAT", cmd_cat, hlp_cat }, - { "NEWDATAPORT", cmd_newdataport, hlp_newdataport }, - { "DATAPORT", cmd_dataport, hlp_dataport }, - { "INPUT", NULL }, - { "OUTPUT", NULL }, - { "GETINFO", cmd_getinfo, hlp_getinfo }, - { "SHUTDOWN", cmd_shutdown, hlp_shutdown }, - { NULL, NULL } - }; - int i; - gpg_error_t rc; - - for (i=0; table[i].name; i++) - { - rc = assuan_register_command (ctx, table[i].name, - table[i].handler, table[i].help); - if (rc) - return rc; - } - return 0; -} - - - -static assuan_fd_t -get_connection_fd (assuan_context_t ctx) -{ - assuan_fd_t fds[5]; - - if (assuan_get_active_fds (ctx, 0, fds, DIM (fds)) < 1) - log_fatal ("assuan_get_active_fds failed\n"); - if (fds[0] == ASSUAN_INVALID_FD) - log_fatal ("assuan_get_active_fds returned invalid conenction fd\n"); - return fds[0]; -} - - -/* Startup the server. */ -static void -server (void) -{ - gpg_error_t err; - assuan_fd_t server_fd; - assuan_sock_nonce_t server_nonce; - int one = 1; - struct sockaddr_in name; - assuan_context_t ctx; - state_t state = NULL; - - err = assuan_new (&ctx); - if (err) - log_fatal ("assuan_new failed: %s\n", gpg_strerror (err)); - - server_fd = assuan_sock_new (PF_INET, SOCK_STREAM, 0); - if (server_fd == ASSUAN_INVALID_FD) - log_fatal ("socket() failed: %s\n", strerror (errno)); - - if (setsockopt (HANDLE2SOCKET (server_fd), - SOL_SOCKET, SO_REUSEADDR, (void*)&one, sizeof one)) - log_error ("setsockopt(SO_REUSEADDR) failed: %s\n", strerror (errno)); - - name.sin_family = AF_INET; - name.sin_port = htons (server_port); - name.sin_addr.s_addr = htonl (INADDR_ANY); - if (assuan_sock_bind (server_fd, (struct sockaddr *) &name, sizeof name)) - log_fatal ("bind() failed: %s\n", strerror (errno)); - if (assuan_sock_get_nonce ((struct sockaddr*)&name, sizeof name, - &server_nonce)) - log_fatal ("assuan_sock_get_nonce failed: %s\n", strerror (errno)); - - /* Register the nonce with the context so that assuan_accept knows - about it. We can't do that directly in assuan_sock_bind because - we want these socket wrappers to be context neutral and drop in - replacement for the standard socket functions. */ - assuan_set_sock_nonce (ctx, &server_nonce); - - if (listen (HANDLE2SOCKET (server_fd), 5)) - log_fatal ("listen() failed: %s\n", strerror (errno)); - - log_info ("server listening on port %hd\n", server_port); - - err = assuan_init_socket_server (ctx, server_fd, 0); - if (err) - log_fatal ("assuan_init_socket_server failed: %s\n", gpg_strerror (err)); - - err = register_commands (ctx); - if (err) - log_fatal ("register_commands failed: %s\n", gpg_strerror(err)); - - if (debug) - assuan_set_log_stream (ctx, stderr); - - assuan_register_reset_notify (ctx, reset_notify); - assuan_register_input_notify (ctx, input_notify); - assuan_register_output_notify (ctx, output_notify); - - - state = new_state (); - - assuan_set_pointer (ctx, state); - - while (!shutdown_pending) - { - int done; - - err = assuan_accept (ctx); - if (err) - { - if (gpg_err_code (err) == GPG_ERR_EOF || err == -1) - log_error ("assuan_accept failed: %s\n", gpg_strerror (err)); - break; - } - - log_info ("client connected. Client's pid is %ld\n", - (long)assuan_get_pid (ctx)); - do - { - /* We need to use select here so that we can accept - supplemental connections from the client as requested by - the DATAPORT command. */ - fd_set rfds; - int connfd, datafd, max_fd; - - connfd = HANDLE2SOCKET (get_connection_fd (ctx)); - FD_ZERO (&rfds); - FD_SET (connfd, &rfds); - max_fd = connfd; - - if (state->dataport_listen_fd != ASSUAN_INVALID_FD) - { - datafd = HANDLE2SOCKET (state->dataport_listen_fd); - FD_SET (datafd, &rfds); - if (datafd > max_fd) - max_fd = datafd; - } - else - datafd = -1; - - if (select (max_fd + 1, &rfds, NULL, NULL, NULL) > 0) - { - if (datafd != -1 && FD_ISSET (datafd, &rfds)) - { - struct sockaddr_in clnt_addr; - socklen_t len = sizeof clnt_addr; - int fd; - - fd = accept (datafd, (struct sockaddr*)&clnt_addr, &len); - if (fd == -1) - { - err = gpg_err_code_from_syserror (); - assuan_sock_close (state->dataport_listen_fd); - state->dataport_listen_fd = ASSUAN_INVALID_FD; - log_error ("accepting on dataport failed: %s\n", - gpg_strerror (err)); - state->dataport_accept_err = err; - err = 0; - } - else - { - /* No more need for the listening socket. */ - assuan_sock_close (state->dataport_listen_fd); - state->dataport_listen_fd = ASSUAN_INVALID_FD; - /* Record the accepted fd. */ - state->dataport_accept_err = 0; - state->dataport_accepted_fd = SOCKET2HANDLE (fd); - } - } - - if (FD_ISSET (connfd, &rfds)) - { - err = assuan_process_next (ctx, &done); - } - } - } - while (!err && !done && !shutdown_pending); - if (err) - log_error ("assuan_process failed: %s\n", gpg_strerror (err)); - } - - assuan_sock_close (server_fd); - assuan_release (ctx); - release_state (state); -} - - - - - -/* - - M A I N - -*/ -int -main (int argc, char **argv) -{ - gpg_error_t err; - int last_argc = -1; - - if (argc) - { - log_set_prefix (*argv); - argc--; argv++; - } - while (argc && last_argc != argc ) - { - last_argc = argc; - if (!strcmp (*argv, "--help")) - { - printf ( - "usage: %s [options]\n" - "\n" - "Options:\n" - " --verbose Show what is going on\n", - log_get_prefix ()); - exit (0); - } - if (!strcmp (*argv, "--verbose")) - { - verbose = 1; - argc--; argv++; - } - else if (!strcmp (*argv, "--debug")) - { - verbose = debug = 1; - argc--; argv++; - } - } - - assuan_set_assuan_log_prefix (log_prefix); - if (debug) - assuan_set_assuan_log_stream (stderr); - - err = assuan_sock_init (); - if (err) - log_fatal ("assuan_sock_init failed: %s\n", gpg_strerror (err)); - - log_info ("server starting...\n"); - server (); - log_info ("server finished\n"); - - assuan_sock_deinit (); - - return errorcount ? 1 : 0; -} diff --git a/tests/common.h b/tests/common.h index c5ce811..dc3c073 100644 --- a/tests/common.h +++ b/tests/common.h @@ -26,11 +26,6 @@ #endif -#ifdef HAVE_W32CE_SYSTEM -#define getpid() GetCurrentProcessId () -#define getenv(a) (NULL) -#endif - #if HAVE_W32_SYSTEM #define SOCKET2HANDLE(s) ((void *)(s)) #define HANDLE2SOCKET(h) ((unsigned int)(h)) diff --git a/tests/pipeconnect.c b/tests/pipeconnect.c index ddb4a06..b477af1 100644 --- a/tests/pipeconnect.c +++ b/tests/pipeconnect.c @@ -247,61 +247,11 @@ run_client (const char *servername) static void parse_std_file_handles (int *argcp, char ***argvp) { -#ifdef HAVE_W32CE_SYSTEM - int argc = *argcp; - char **argv = *argvp; - const char *s; - assuan_fd_t fd; - int i; - int fixup = 0; - - if (!argc) - return; - - for (argc--, argv++; argc; argc--, argv++) - { - s = *argv; - if (*s == '-' && s[1] == '&' && s[2] == 'S' - && (s[3] == '0' || s[3] == '1' || s[3] == '2') - && s[4] == '=' - && (strchr ("-01234567890", s[5]) || !strcmp (s+5, "null"))) - { - if (s[5] == 'n') - fd = ASSUAN_INVALID_FD; - else - fd = _assuan_w32ce_finish_pipe (atoi (s+5), s[3] != '0'); - switch (s[3] - '0') - { - case 0: my_stdin = fd; break; - case 1: my_stdout = fd; break; - case 2: my_stderr = fd; break; - } - - fixup++; - } - else - break; - } - - if (fixup) - { - argc = *argcp; - argc -= fixup; - *argcp = argc; - - argv = *argvp; - for (i=1; i < argc; i++) - argv[i] = argv[i + fixup]; - for (; i < argc + fixup; i++) - argv[i] = NULL; - } -#else (void)argcp; (void)argvp; my_stdin = 0; my_stdout = 1; my_stderr = 2; -#endif } -- cgit v1.2.1