2007-09-07 Marcus Brinkmann <marcus@g10code.de>
* configure.ac: Check for C++, Qt and support --enable-w32-qt. * m4/pkg.m4: New file. gpgme/ 2007-09-07 Marcus Brinkmann <marcus@g10code.de> * kdpipeiodevice.h, kdpipeiodevice.cpp, moc_kdpipeiodevice.cpp, kdpipeiodevice.moc, w32-qt-io.c: New files. * Makefile.am (ltlib_gpgme_extra): Rename to ltlib_gpgme_glib. (ltlib_gpgme_qt): New variable. (lib_LTLIBRARIES): Add $(ltlib_gpgme_qt). (libgpgme_qt_la_SOURCES): New variable. (AM_CPPFLAGS): Add @QT4_CORE_INCLUDES@ (AM_CFLAGS): Add @QT4_CORE_CFLAGS@. (libgpgme_qt_la_LDFLAGS, libgpgme_qt_la_DEPENDENCIES) (libgpgme_qt_la_LIBADD): New variables. * sema.h (struct critsect_s): Rename "private" to "priv" to make C++ users happy. Change users. * posix-sema.c (_gpgme_sema_cs_enter, _gpgme_sema_cs_leave) (_gpgme_sema_cs_destroy): Likewise. * w32-sema.c (critsect_init, _gpgme_sema_cs_enter) (_gpgme_sema_cs_leave, _gpgme_sema_cs_destroy): Likewise. * w32-glib-io.c (gpgme_get_giochannel): Change return type to void*. (gpgme_get_fdptr): New function. * w32-io.c (gpgme_get_fdptr): New function * gpgme.def: Add gpgme_get_fdptr.
This commit is contained in:
parent
e8b5e9321d
commit
becf580f61
@ -1,3 +1,8 @@
|
|||||||
|
2007-09-07 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
|
* configure.ac: Check for C++, Qt and support --enable-w32-qt.
|
||||||
|
* m4/pkg.m4: New file.
|
||||||
|
|
||||||
2007-08-21 Marcus Brinkmann <marcus@g10code.de>
|
2007-08-21 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
* configure.ac (--enable-w32-glib): Use --enableval, not
|
* configure.ac (--enable-w32-glib): Use --enableval, not
|
||||||
@ -775,7 +780,7 @@
|
|||||||
* autogen.sh: Added option --build-w32.
|
* autogen.sh: Added option --build-w32.
|
||||||
|
|
||||||
|
|
||||||
Copyright 2001, 2002, 2003, 2004, 2005 g10 Code GmbH
|
Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007 g10 Code GmbH
|
||||||
|
|
||||||
This file is free software; as a special exception the author gives
|
This file is free software; as a special exception the author gives
|
||||||
unlimited permission to copy and/or distribute it, with or without
|
unlimited permission to copy and/or distribute it, with or without
|
||||||
|
@ -83,6 +83,7 @@ AH_VERBATIM([_REENTRANT],
|
|||||||
#endif])
|
#endif])
|
||||||
|
|
||||||
AC_PROG_CC
|
AC_PROG_CC
|
||||||
|
AC_PROG_CXX
|
||||||
|
|
||||||
AC_SUBST(LIBGPGME_LT_CURRENT)
|
AC_SUBST(LIBGPGME_LT_CURRENT)
|
||||||
AC_SUBST(LIBGPGME_LT_AGE)
|
AC_SUBST(LIBGPGME_LT_AGE)
|
||||||
@ -162,6 +163,13 @@ AC_ARG_ENABLE(w32-glib,
|
|||||||
build_w32_glib=$enableval)
|
build_w32_glib=$enableval)
|
||||||
AM_CONDITIONAL(BUILD_W32_GLIB, test "$build_w32_glib" = yes)
|
AM_CONDITIONAL(BUILD_W32_GLIB, test "$build_w32_glib" = yes)
|
||||||
|
|
||||||
|
build_w32_qt=no
|
||||||
|
PKG_CHECK_MODULES(QT4_CORE, QtCore)
|
||||||
|
AC_ARG_ENABLE(w32-qt,
|
||||||
|
AC_HELP_STRING([--enable-w32-qt], [build GPGME Qt for W32]),
|
||||||
|
build_w32_qt=$enableval)
|
||||||
|
AM_CONDITIONAL(BUILD_W32_QT, test "$build_w32_qt" = yes)
|
||||||
|
|
||||||
AM_CONDITIONAL(HAVE_PTH, test "$have_pth" = "yes")
|
AM_CONDITIONAL(HAVE_PTH, test "$have_pth" = "yes")
|
||||||
AM_CONDITIONAL(HAVE_PTHREAD, test "$have_pthread" = "yes")
|
AM_CONDITIONAL(HAVE_PTHREAD, test "$have_pthread" = "yes")
|
||||||
|
|
||||||
|
@ -1,3 +1,27 @@
|
|||||||
|
2007-09-07 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
|
* kdpipeiodevice.h, kdpipeiodevice.cpp, moc_kdpipeiodevice.cpp,
|
||||||
|
kdpipeiodevice.moc, w32-qt-io.c: New files.
|
||||||
|
* Makefile.am (ltlib_gpgme_extra): Rename to ltlib_gpgme_glib.
|
||||||
|
(ltlib_gpgme_qt): New variable.
|
||||||
|
(lib_LTLIBRARIES): Add $(ltlib_gpgme_qt).
|
||||||
|
(libgpgme_qt_la_SOURCES): New variable.
|
||||||
|
(AM_CPPFLAGS): Add @QT4_CORE_INCLUDES@
|
||||||
|
(AM_CFLAGS): Add @QT4_CORE_CFLAGS@.
|
||||||
|
(libgpgme_qt_la_LDFLAGS, libgpgme_qt_la_DEPENDENCIES)
|
||||||
|
(libgpgme_qt_la_LIBADD): New variables.
|
||||||
|
* sema.h (struct critsect_s): Rename "private" to "priv" to make
|
||||||
|
C++ users happy. Change users.
|
||||||
|
* posix-sema.c (_gpgme_sema_cs_enter, _gpgme_sema_cs_leave)
|
||||||
|
(_gpgme_sema_cs_destroy): Likewise.
|
||||||
|
* w32-sema.c (critsect_init, _gpgme_sema_cs_enter)
|
||||||
|
(_gpgme_sema_cs_leave, _gpgme_sema_cs_destroy): Likewise.
|
||||||
|
* w32-glib-io.c (gpgme_get_giochannel): Change return type to
|
||||||
|
void*.
|
||||||
|
(gpgme_get_fdptr): New function.
|
||||||
|
* w32-io.c (gpgme_get_fdptr): New function
|
||||||
|
* gpgme.def: Add gpgme_get_fdptr.
|
||||||
|
|
||||||
2007-08-22 Marcus Brinkmann <marcus@g10code.de>
|
2007-08-22 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
* w32-io.c (_gpgme_io_write): Return early if COUNT is zero.
|
* w32-io.c (_gpgme_io_write): Return early if COUNT is zero.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# Copyright (C) 2000 Werner Koch (dd9jn)
|
# Copyright (C) 2000 Werner Koch (dd9jn)
|
||||||
# Copyright (C) 2001, 2002, 2003, 2004, 2005 g10 Code GmbH
|
# Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007 g10 Code GmbH
|
||||||
#
|
#
|
||||||
# This file is part of GPGME.
|
# This file is part of GPGME.
|
||||||
#
|
#
|
||||||
@ -40,12 +40,18 @@ ltlib_gpgme_pth =
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
if BUILD_W32_GLIB
|
if BUILD_W32_GLIB
|
||||||
ltlib_gpgme_extra = libgpgme-glib.la
|
ltlib_gpgme_glib = libgpgme-glib.la
|
||||||
else
|
else
|
||||||
ltlib_gpgme_extra =
|
ltlib_gpgme_glib =
|
||||||
endif
|
endif
|
||||||
|
|
||||||
lib_LTLIBRARIES = libgpgme.la $(ltlib_gpgme_extra) \
|
if BUILD_W32_QT
|
||||||
|
ltlib_gpgme_qt = libgpgme-qt.la
|
||||||
|
else
|
||||||
|
ltlib_gpgme_qt =
|
||||||
|
endif
|
||||||
|
|
||||||
|
lib_LTLIBRARIES = libgpgme.la $(ltlib_gpgme_glib) $(ltlib_gpgme_qt) \
|
||||||
$(ltlib_gpgme_pthread) $(ltlib_gpgme_pth)
|
$(ltlib_gpgme_pthread) $(ltlib_gpgme_pth)
|
||||||
|
|
||||||
if HAVE_LD_VERSION_SCRIPT
|
if HAVE_LD_VERSION_SCRIPT
|
||||||
@ -107,10 +113,24 @@ if BUILD_W32_GLIB
|
|||||||
libgpgme_glib_la_SOURCES = $(main_sources) ath.h ath.c w32-glib-io.c
|
libgpgme_glib_la_SOURCES = $(main_sources) ath.h ath.c w32-glib-io.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if BUILD_W32_QT
|
||||||
|
libgpgme_qt_la_SOURCES = $(main_sources) ath.h ath.c w32-qt-io.cpp \
|
||||||
|
kdpipeiodevice.h kdpipeiodevice.cpp moc_kdpipeiodevice.cpp \
|
||||||
|
kdpipeiodevice.moc
|
||||||
|
|
||||||
|
# These are built sources (normally).
|
||||||
|
# moc_kdpipeiodevice.cpp: kdpipeiodevice.h
|
||||||
|
# $(MOC4) -o $@ $<
|
||||||
|
#
|
||||||
|
# kdpipeiodevice.moc: kdpipeiodevice.cpp
|
||||||
|
# $(MOC4) -o $@ $<
|
||||||
|
endif
|
||||||
|
|
||||||
# We use a global CFLAGS and CPPFLAGS setting for all library
|
# We use a global CFLAGS and CPPFLAGS setting for all library
|
||||||
# versions, because then every object file is only compiled once.
|
# versions, because then every object file is only compiled once.
|
||||||
AM_CPPFLAGS = $(assuan_cppflags) @GPG_ERROR_CFLAGS@ @PTH_CPPFLAGS@
|
AM_CPPFLAGS = $(assuan_cppflags) @GPG_ERROR_CFLAGS@ @PTH_CPPFLAGS@ \
|
||||||
AM_CFLAGS = @PTH_CFLAGS@ @GLIB_CFLAGS@
|
@QT4_CORE_CFLAGS@
|
||||||
|
AM_CFLAGS = @PTH_CFLAGS@ @GLIB_CFLAGS@ @QT4_CORE_CFLAGS@
|
||||||
|
|
||||||
if HAVE_W32_SYSTEM
|
if HAVE_W32_SYSTEM
|
||||||
|
|
||||||
@ -181,6 +201,16 @@ libgpgme_glib_la_LIBADD = $(assuan_libobjs) @LTLIBOBJS@ \
|
|||||||
@GPG_ERROR_LIBS@ @GLIB_LIBS@ @NETLIBS@
|
@GPG_ERROR_LIBS@ @GLIB_LIBS@ @NETLIBS@
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if BUILD_W32_QT
|
||||||
|
libgpgme_qt_la_LDFLAGS = $(gpgme_res_ldflag) $(no_undefined) \
|
||||||
|
$(export_symbols) $(libgpgme_version_script_cmd) -version-info \
|
||||||
|
@LIBGPGME_LT_CURRENT@:@LIBGPGME_LT_REVISION@:@LIBGPGME_LT_AGE@
|
||||||
|
libgpgme_qt_la_DEPENDENCIES = $(assuan_libobjs) \
|
||||||
|
@LTLIBOBJS@ $(srcdir)/libgpgme.vers $(gpgme_deps)
|
||||||
|
libgpgme_qt_la_LIBADD = $(assuan_libobjs) @LTLIBOBJS@ \
|
||||||
|
@GPG_ERROR_LIBS@ @QT4_CORE_LIB@ @NETLIBS@
|
||||||
|
endif
|
||||||
|
|
||||||
status-table.h : gpgme.h
|
status-table.h : gpgme.h
|
||||||
$(srcdir)/mkstatus < $(srcdir)/gpgme.h > status-table.h
|
$(srcdir)/mkstatus < $(srcdir)/gpgme.h > status-table.h
|
||||||
|
|
||||||
|
@ -154,5 +154,7 @@ EXPORTS
|
|||||||
gpgme_free @120
|
gpgme_free @120
|
||||||
|
|
||||||
gpgme_get_giochannel @121
|
gpgme_get_giochannel @121
|
||||||
|
gpgme_get_fdptr @122
|
||||||
|
|
||||||
; END
|
; END
|
||||||
|
|
||||||
|
760
gpgme/kdpipeiodevice.cpp
Normal file
760
gpgme/kdpipeiodevice.cpp
Normal file
@ -0,0 +1,760 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2007 Klarälvdalens Datakonsult AB
|
||||||
|
|
||||||
|
KDPipeIODevice is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
KDPipeIODevice 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 Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public License
|
||||||
|
along with KDPipeIODevice; see the file COPYING.LIB. If not, write to the
|
||||||
|
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "kdpipeiodevice.h"
|
||||||
|
|
||||||
|
#include <QtCore>
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <memory>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN32
|
||||||
|
# define NOMINMAX
|
||||||
|
# include <windows.h>
|
||||||
|
# include <io.h>
|
||||||
|
#else
|
||||||
|
# include <unistd.h>
|
||||||
|
# include <errno.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef KDAB_CHECK_THIS
|
||||||
|
# define KDAB_CHECK_CTOR (void)1
|
||||||
|
# define KDAB_CHECK_DTOR KDAB_CHECK_CTOR
|
||||||
|
# define KDAB_CHECK_THIS KDAB_CHECK_CTOR
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define LOCKED( d ) const QMutexLocker locker( &d->mutex )
|
||||||
|
#define synchronized( d ) if ( int i = 0 ) {} else for ( const QMutexLocker locker( &d->mutex ) ; !i ; ++i )
|
||||||
|
|
||||||
|
const unsigned int BUFFER_SIZE = 4096;
|
||||||
|
const bool ALLOW_QIODEVICE_BUFFERING = true;
|
||||||
|
|
||||||
|
// comment to get trace output:
|
||||||
|
#define qDebug if(1){}else qDebug
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
class Reader : public QThread {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
Reader( int fd, Qt::HANDLE handle );
|
||||||
|
~Reader();
|
||||||
|
|
||||||
|
qint64 readData( char * data, qint64 maxSize );
|
||||||
|
|
||||||
|
unsigned int bytesInBuffer() const {
|
||||||
|
return ( wptr + sizeof buffer - rptr ) % sizeof buffer ;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bufferFull() const {
|
||||||
|
return bytesInBuffer() == sizeof buffer - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bufferEmpty() const {
|
||||||
|
return bytesInBuffer() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bufferContains( char ch ) {
|
||||||
|
const unsigned int bib = bytesInBuffer();
|
||||||
|
for ( unsigned int i = rptr ; i < rptr + bib ; ++i )
|
||||||
|
if ( buffer[i%sizeof buffer] == ch )
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void readyRead();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/* reimp */ void run();
|
||||||
|
|
||||||
|
private:
|
||||||
|
int fd;
|
||||||
|
Qt::HANDLE handle;
|
||||||
|
public:
|
||||||
|
QMutex mutex;
|
||||||
|
QWaitCondition bufferNotFullCondition;
|
||||||
|
QWaitCondition bufferNotEmptyCondition;
|
||||||
|
QWaitCondition hasStarted;
|
||||||
|
bool cancel;
|
||||||
|
bool eof;
|
||||||
|
bool error;
|
||||||
|
bool eofShortCut;
|
||||||
|
int errorCode;
|
||||||
|
private:
|
||||||
|
unsigned int rptr, wptr;
|
||||||
|
char buffer[BUFFER_SIZE+1]; // need to keep one byte free to detect empty state
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Reader::Reader( int fd_, Qt::HANDLE handle_ )
|
||||||
|
: QThread(),
|
||||||
|
fd( fd_ ),
|
||||||
|
handle( handle_ ),
|
||||||
|
mutex(),
|
||||||
|
bufferNotFullCondition(),
|
||||||
|
bufferNotEmptyCondition(),
|
||||||
|
hasStarted(),
|
||||||
|
cancel( false ),
|
||||||
|
eof( false ),
|
||||||
|
error( false ),
|
||||||
|
eofShortCut( false ),
|
||||||
|
errorCode( 0 ),
|
||||||
|
rptr( 0 ), wptr( 0 )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Reader::~Reader() {}
|
||||||
|
|
||||||
|
|
||||||
|
class Writer : public QThread {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
Writer( int fd, Qt::HANDLE handle );
|
||||||
|
~Writer();
|
||||||
|
|
||||||
|
qint64 writeData( const char * data, qint64 size );
|
||||||
|
|
||||||
|
unsigned int bytesInBuffer() const { return numBytesInBuffer; }
|
||||||
|
|
||||||
|
bool bufferFull() const {
|
||||||
|
return numBytesInBuffer == sizeof buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bufferEmpty() const {
|
||||||
|
return numBytesInBuffer == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void bytesWritten( qint64 );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/* reimp */ void run();
|
||||||
|
|
||||||
|
private:
|
||||||
|
int fd;
|
||||||
|
Qt::HANDLE handle;
|
||||||
|
public:
|
||||||
|
QMutex mutex;
|
||||||
|
QWaitCondition bufferEmptyCondition;
|
||||||
|
QWaitCondition bufferNotEmptyCondition;
|
||||||
|
QWaitCondition hasStarted;
|
||||||
|
bool cancel;
|
||||||
|
bool error;
|
||||||
|
int errorCode;
|
||||||
|
private:
|
||||||
|
unsigned int numBytesInBuffer;
|
||||||
|
char buffer[BUFFER_SIZE];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Writer::Writer( int fd_, Qt::HANDLE handle_ )
|
||||||
|
: QThread(),
|
||||||
|
fd( fd_ ),
|
||||||
|
handle( handle_ ),
|
||||||
|
mutex(),
|
||||||
|
bufferEmptyCondition(),
|
||||||
|
bufferNotEmptyCondition(),
|
||||||
|
hasStarted(),
|
||||||
|
cancel( false ),
|
||||||
|
error( false ),
|
||||||
|
errorCode( 0 ),
|
||||||
|
numBytesInBuffer( 0 )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Writer::~Writer() {}
|
||||||
|
|
||||||
|
|
||||||
|
class KDPipeIODevice::Private {
|
||||||
|
friend class ::KDPipeIODevice;
|
||||||
|
KDPipeIODevice * const q;
|
||||||
|
public:
|
||||||
|
explicit Private( KDPipeIODevice * qq );
|
||||||
|
~Private();
|
||||||
|
|
||||||
|
bool doOpen( int, Qt::HANDLE, OpenMode );
|
||||||
|
|
||||||
|
private:
|
||||||
|
int fd;
|
||||||
|
Qt::HANDLE handle;
|
||||||
|
Reader * reader;
|
||||||
|
Writer * writer;
|
||||||
|
};
|
||||||
|
|
||||||
|
KDPipeIODevice::Private::Private( KDPipeIODevice * qq )
|
||||||
|
: q( qq ),
|
||||||
|
fd( -1 ),
|
||||||
|
handle( 0 ),
|
||||||
|
reader( 0 ),
|
||||||
|
writer( 0 )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
KDPipeIODevice::Private::~Private() {}
|
||||||
|
|
||||||
|
|
||||||
|
KDPipeIODevice::KDPipeIODevice( QObject * p )
|
||||||
|
: QIODevice( p ), d( new Private( this ) )
|
||||||
|
{
|
||||||
|
KDAB_CHECK_CTOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
KDPipeIODevice::KDPipeIODevice( int fd, OpenMode mode, QObject * p )
|
||||||
|
: QIODevice( p ), d( new Private( this ) )
|
||||||
|
{
|
||||||
|
KDAB_CHECK_CTOR;
|
||||||
|
open( fd, mode );
|
||||||
|
}
|
||||||
|
|
||||||
|
KDPipeIODevice::KDPipeIODevice( Qt::HANDLE handle, OpenMode mode, QObject * p )
|
||||||
|
: QIODevice( p ), d( new Private( this ) )
|
||||||
|
{
|
||||||
|
KDAB_CHECK_CTOR;
|
||||||
|
open( handle, mode );
|
||||||
|
}
|
||||||
|
|
||||||
|
KDPipeIODevice::~KDPipeIODevice() { KDAB_CHECK_DTOR;
|
||||||
|
if ( isOpen() )
|
||||||
|
close();
|
||||||
|
delete d; d = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool KDPipeIODevice::open( int fd, OpenMode mode ) { KDAB_CHECK_THIS;
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN32
|
||||||
|
return d->doOpen( fd, (HANDLE)_get_osfhandle( fd ), mode );
|
||||||
|
#else
|
||||||
|
return d->doOpen( fd, 0, mode );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KDPipeIODevice::open( Qt::HANDLE h, OpenMode mode ) { KDAB_CHECK_THIS;
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN32
|
||||||
|
return d->doOpen( 0, h, mode );
|
||||||
|
#else
|
||||||
|
Q_UNUSED( h );
|
||||||
|
Q_UNUSED( mode );
|
||||||
|
assert( !"KDPipeIODevice::open( Qt::HANDLE, OpenMode ) should never be called except on Windows." );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KDPipeIODevice::Private::doOpen( int fd_, Qt::HANDLE handle_, OpenMode mode_ ) {
|
||||||
|
|
||||||
|
if ( q->isOpen() || fd_ < 0 )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN32
|
||||||
|
if ( !handle_ )
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ( !(mode_ & ReadWrite) )
|
||||||
|
return false; // need to have at least read -or- write
|
||||||
|
|
||||||
|
fd = fd_;
|
||||||
|
handle = handle_;
|
||||||
|
|
||||||
|
std::auto_ptr<Reader> reader_;
|
||||||
|
std::auto_ptr<Writer> writer_;
|
||||||
|
|
||||||
|
if ( mode_ & ReadOnly ) {
|
||||||
|
reader_.reset( new Reader( fd_, handle_ ) );
|
||||||
|
LOCKED( reader_ );
|
||||||
|
reader_->start( QThread::HighestPriority );
|
||||||
|
if ( !reader_->hasStarted.wait( &reader_->mutex, 1000 ) )
|
||||||
|
return false;
|
||||||
|
connect( reader_.get(), SIGNAL(readyRead()), q, SIGNAL(readyRead()), Qt::QueuedConnection );
|
||||||
|
}
|
||||||
|
if ( mode_ & WriteOnly ) {
|
||||||
|
writer_.reset( new Writer( fd_, handle_ ) );
|
||||||
|
LOCKED( writer_ );
|
||||||
|
writer_->start( QThread::HighestPriority );
|
||||||
|
if ( !writer_->hasStarted.wait( &writer_->mutex, 1000 ) )
|
||||||
|
return false;
|
||||||
|
connect( writer_.get(), SIGNAL(bytesWritten(qint64)), q, SIGNAL(bytesWritten(qint64)), Qt::QueuedConnection );
|
||||||
|
}
|
||||||
|
|
||||||
|
// commit to *this:
|
||||||
|
fd = fd_;
|
||||||
|
handle = handle_;
|
||||||
|
reader = reader_.release();
|
||||||
|
writer = writer_.release();
|
||||||
|
|
||||||
|
q->setOpenMode( mode_|Unbuffered );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int KDPipeIODevice::descriptor() const { KDAB_CHECK_THIS;
|
||||||
|
return d->fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::HANDLE KDPipeIODevice::handle() const { KDAB_CHECK_THIS;
|
||||||
|
return d->handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 KDPipeIODevice::bytesAvailable() const { KDAB_CHECK_THIS;
|
||||||
|
const qint64 base = QIODevice::bytesAvailable();
|
||||||
|
if ( d->reader )
|
||||||
|
synchronized( d->reader ) return base + d->reader->bytesInBuffer();
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 KDPipeIODevice::bytesToWrite() const { KDAB_CHECK_THIS;
|
||||||
|
const qint64 base = QIODevice::bytesToWrite();
|
||||||
|
if ( d->writer )
|
||||||
|
synchronized( d->writer ) return base + d->writer->bytesInBuffer();
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KDPipeIODevice::canReadLine() const { KDAB_CHECK_THIS;
|
||||||
|
if ( QIODevice::canReadLine() )
|
||||||
|
return true;
|
||||||
|
if ( d->reader )
|
||||||
|
synchronized( d->reader ) return d->reader->bufferContains( '\n' );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KDPipeIODevice::isSequential() const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KDPipeIODevice::atEnd() const { KDAB_CHECK_THIS;
|
||||||
|
if ( !QIODevice::atEnd() ) {
|
||||||
|
qDebug( "KDPipeIODevice::atEnd returns false since QIODevice::atEnd does (with bytesAvailable=%ld)", static_cast<long>(bytesAvailable()) );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !isOpen() )
|
||||||
|
return true;
|
||||||
|
if ( d->reader->eofShortCut )
|
||||||
|
return true;
|
||||||
|
LOCKED( d->reader );
|
||||||
|
const bool eof = ( d->reader->error || d->reader->eof ) && d->reader->bufferEmpty();
|
||||||
|
if ( !eof ) {
|
||||||
|
if ( !d->reader->error && !d->reader->eof )
|
||||||
|
qDebug( "KDPipeIODevice::atEnd returns false since !reader->error && !reader->eof" );
|
||||||
|
if ( !d->reader->bufferEmpty() )
|
||||||
|
qDebug( "KDPipeIODevice::atEnd returns false since !reader->bufferEmpty()" );
|
||||||
|
}
|
||||||
|
return eof;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KDPipeIODevice::waitForBytesWritten( int msecs ) { KDAB_CHECK_THIS;
|
||||||
|
Writer * const w = d->writer;
|
||||||
|
if ( !w )
|
||||||
|
return true;
|
||||||
|
LOCKED( w );
|
||||||
|
return w->bufferEmpty() || w->error || w->bufferEmptyCondition.wait( &w->mutex, msecs ) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KDPipeIODevice::waitForReadyRead( int msecs ) { KDAB_CHECK_THIS;
|
||||||
|
if ( ALLOW_QIODEVICE_BUFFERING ) {
|
||||||
|
if ( bytesAvailable() > 0 )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Reader * const r = d->reader;
|
||||||
|
if ( !r || r->eofShortCut )
|
||||||
|
return true;
|
||||||
|
LOCKED( r );
|
||||||
|
return r->bytesInBuffer() != 0 || r->eof || r->error || r->bufferNotEmptyCondition.wait( &r->mutex, msecs ) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 KDPipeIODevice::readData( char * data, qint64 maxSize ) { KDAB_CHECK_THIS;
|
||||||
|
|
||||||
|
qDebug( "KDPipeIODevice::readData: data=%p, maxSize=%lld", data, maxSize );
|
||||||
|
|
||||||
|
Reader * const r = d->reader;
|
||||||
|
|
||||||
|
assert( r );
|
||||||
|
//assert( r->isRunning() ); // wrong (might be eof, error)
|
||||||
|
assert( data || maxSize == 0 );
|
||||||
|
assert( maxSize >= 0 );
|
||||||
|
|
||||||
|
if ( r->eofShortCut ) {
|
||||||
|
qDebug( "KDPipeIODevice::readData: hit eofShortCut, returning 0" );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( maxSize < 0 )
|
||||||
|
maxSize = 0;
|
||||||
|
|
||||||
|
if ( ALLOW_QIODEVICE_BUFFERING ) {
|
||||||
|
if ( bytesAvailable() > 0 )
|
||||||
|
maxSize = std::min( maxSize, bytesAvailable() ); // don't block
|
||||||
|
}
|
||||||
|
|
||||||
|
LOCKED( r );
|
||||||
|
if ( /* maxSize > 0 && */ r->bufferEmpty() && !r->error && !r->eof ) { // ### block on maxSize == 0?
|
||||||
|
qDebug( "KDPipeIODevice::readData: waiting for bufferNotEmptyCondition" );
|
||||||
|
r->bufferNotEmptyCondition.wait( &r->mutex );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( r->bufferEmpty() ) {
|
||||||
|
qDebug( "KDPipeIODevice::readData: got empty buffer, signal eof" );
|
||||||
|
// woken with an empty buffer must mean either EOF or error:
|
||||||
|
assert( r->eof || r->error );
|
||||||
|
r->eofShortCut = true;
|
||||||
|
return r->eof ? 0 : -1 ;
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug( "KDPipeIODevice::readData: got bufferNotEmptyCondition, trying to read %lld bytes", maxSize );
|
||||||
|
const qint64 bytesRead = r->readData( data, maxSize );
|
||||||
|
qDebug( "KDPipeIODevice::readData: read %lld bytes", bytesRead );
|
||||||
|
return bytesRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 Reader::readData( char * data, qint64 maxSize ) {
|
||||||
|
|
||||||
|
qint64 numRead = rptr < wptr ? wptr - rptr : sizeof buffer - rptr ;
|
||||||
|
if ( numRead > maxSize )
|
||||||
|
numRead = maxSize;
|
||||||
|
|
||||||
|
qDebug( "KDPipeIODevice::readData: data=%p, maxSize=%lld; rptr=%u, wptr=%u (bytesInBuffer=%u); -> numRead=%lld",
|
||||||
|
data, maxSize, rptr, wptr, bytesInBuffer(), numRead );
|
||||||
|
|
||||||
|
std::memcpy( data, buffer + rptr, numRead );
|
||||||
|
|
||||||
|
rptr = ( rptr + numRead ) % sizeof buffer ;
|
||||||
|
|
||||||
|
if ( !bufferFull() ) {
|
||||||
|
qDebug( "KDPipeIODevice::readData: signal bufferNotFullCondition" );
|
||||||
|
bufferNotFullCondition.wakeAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
return numRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 KDPipeIODevice::writeData( const char * data, qint64 size ) { KDAB_CHECK_THIS;
|
||||||
|
|
||||||
|
Writer * const w = d->writer;
|
||||||
|
|
||||||
|
assert( w );
|
||||||
|
assert( w->error || w->isRunning() );
|
||||||
|
assert( data || size == 0 );
|
||||||
|
assert( size >= 0 );
|
||||||
|
|
||||||
|
LOCKED( w );
|
||||||
|
|
||||||
|
while ( !w->error && !w->bufferEmpty() )
|
||||||
|
w->bufferEmptyCondition.wait( &w->mutex );
|
||||||
|
|
||||||
|
if ( w->error )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
assert( w->bufferEmpty() );
|
||||||
|
|
||||||
|
return w->writeData( data, size );
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 Writer::writeData( const char * data, qint64 size ) {
|
||||||
|
|
||||||
|
assert( bufferEmpty() );
|
||||||
|
|
||||||
|
if ( size > static_cast<qint64>( sizeof buffer ) )
|
||||||
|
size = sizeof buffer;
|
||||||
|
|
||||||
|
std::memcpy( buffer, data, size );
|
||||||
|
|
||||||
|
numBytesInBuffer = size;
|
||||||
|
|
||||||
|
if ( !bufferEmpty() )
|
||||||
|
bufferNotEmptyCondition.wakeAll();
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KDPipeIODevice::close() { KDAB_CHECK_THIS;
|
||||||
|
|
||||||
|
if ( !isOpen() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// tell clients we're about to close:
|
||||||
|
emit aboutToClose();
|
||||||
|
|
||||||
|
if ( d->writer && bytesToWrite() > 0 )
|
||||||
|
waitForBytesWritten( -1 );
|
||||||
|
|
||||||
|
assert( bytesToWrite() == 0 );
|
||||||
|
|
||||||
|
if ( Reader * & r = d->reader ) {
|
||||||
|
synchronized( r ) {
|
||||||
|
// tell thread to cancel:
|
||||||
|
r->cancel = true;
|
||||||
|
// and wake it, so it can terminate:
|
||||||
|
r->bufferNotFullCondition.wakeAll();
|
||||||
|
}
|
||||||
|
r->wait();
|
||||||
|
delete r; r = 0;
|
||||||
|
}
|
||||||
|
if ( Writer * & w = d->writer ) {
|
||||||
|
synchronized( w ) {
|
||||||
|
// tell thread to cancel:
|
||||||
|
w->cancel = true;
|
||||||
|
// and wake it, so it can terminate:
|
||||||
|
w->bufferNotEmptyCondition.wakeAll();
|
||||||
|
}
|
||||||
|
w->wait();
|
||||||
|
delete w; w = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN32
|
||||||
|
CloseHandle( d->handle );
|
||||||
|
#else
|
||||||
|
::close( d->fd );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
setOpenMode( NotOpen );
|
||||||
|
d->fd = -1;
|
||||||
|
d->handle = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Reader::run() {
|
||||||
|
|
||||||
|
LOCKED( this );
|
||||||
|
|
||||||
|
// too bad QThread doesn't have that itself; a signal isn't enough
|
||||||
|
hasStarted.wakeAll();
|
||||||
|
|
||||||
|
qDebug( "Reader::run: started" );
|
||||||
|
|
||||||
|
while ( true ) {
|
||||||
|
|
||||||
|
while ( !cancel && bufferFull() ) {
|
||||||
|
bufferNotEmptyCondition.wakeAll();
|
||||||
|
qDebug( "Reader::run: buffer is full, going to sleep" );
|
||||||
|
bufferNotFullCondition.wait( &mutex );
|
||||||
|
qDebug( "Reader::run: woke up" );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( cancel ) {
|
||||||
|
qDebug( "Reader::run: detected cancel" );
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( rptr == wptr ) // optimize for larger chunks in case the buffer is empty
|
||||||
|
rptr = wptr = 0;
|
||||||
|
|
||||||
|
unsigned int numBytes = ( rptr + sizeof buffer - wptr - 1 ) % sizeof buffer;
|
||||||
|
if ( numBytes > sizeof buffer - wptr )
|
||||||
|
numBytes = sizeof buffer - wptr;
|
||||||
|
|
||||||
|
qDebug( "Reader::run: rptr=%d, wptr=%d -> numBytes=%d", rptr, wptr, numBytes );
|
||||||
|
|
||||||
|
assert( numBytes > 0 );
|
||||||
|
|
||||||
|
qDebug( "Reader::run: trying to read %d bytes", numBytes );
|
||||||
|
#ifdef Q_OS_WIN32
|
||||||
|
DWORD numRead;
|
||||||
|
mutex.unlock();
|
||||||
|
const bool ok = ReadFile( handle, buffer + wptr, numBytes, &numRead, 0 );
|
||||||
|
mutex.lock();
|
||||||
|
if ( !ok ) {
|
||||||
|
errorCode = static_cast<int>( GetLastError() );
|
||||||
|
if ( errorCode == ERROR_BROKEN_PIPE ) {
|
||||||
|
qDebug( "Reader::run: got eof" );
|
||||||
|
eof = true;
|
||||||
|
} else {
|
||||||
|
qDebug( "Reader::run: got error: %d", errorCode );
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
qint64 numRead;
|
||||||
|
mutex.unlock();
|
||||||
|
do {
|
||||||
|
numRead = ::read( fd, buffer + wptr, numBytes );
|
||||||
|
} while ( numRead == -1 && errno == EINTR );
|
||||||
|
mutex.lock();
|
||||||
|
|
||||||
|
if ( numRead < 0 ) {
|
||||||
|
errorCode = errno;
|
||||||
|
error = true;
|
||||||
|
qDebug( "Reader::run: got error: %d", errorCode );
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
qDebug( "Reader::run: read %ld bytes", static_cast<long>(numRead) );
|
||||||
|
if ( numRead == 0 ) {
|
||||||
|
qDebug( "Reader::run: eof detected" );
|
||||||
|
eof = true;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( cancel ) {
|
||||||
|
qDebug( "Reader::run: detected cancel" );
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
qDebug( "Reader::run: buffer before: rptr=%4d, wptr=%4d", rptr, wptr );
|
||||||
|
wptr = ( wptr + numRead ) % sizeof buffer;
|
||||||
|
qDebug( "Reader::run: buffer after: rptr=%4d, wptr=%4d", rptr, wptr );
|
||||||
|
if ( !bufferEmpty() ) {
|
||||||
|
qDebug( "Reader::run: buffer no longer empty, waking everyone" );
|
||||||
|
bufferNotEmptyCondition.wakeAll();
|
||||||
|
emit readyRead();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
leave:
|
||||||
|
qDebug( "Reader::run: terminating" );
|
||||||
|
bufferNotEmptyCondition.wakeAll();
|
||||||
|
emit readyRead();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Writer::run() {
|
||||||
|
|
||||||
|
LOCKED( this );
|
||||||
|
|
||||||
|
// too bad QThread doesn't have that itself; a signal isn't enough
|
||||||
|
hasStarted.wakeAll();
|
||||||
|
|
||||||
|
qDebug( "Writer::run: started" );
|
||||||
|
|
||||||
|
while ( true ) {
|
||||||
|
|
||||||
|
while ( !cancel && bufferEmpty() ) {
|
||||||
|
bufferEmptyCondition.wakeAll();
|
||||||
|
qDebug( "Writer::run: buffer is empty, going to sleep" );
|
||||||
|
bufferNotEmptyCondition.wait( &mutex );
|
||||||
|
qDebug( "Writer::run: woke up" );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( cancel ) {
|
||||||
|
qDebug( "Writer::run: detected cancel" );
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert( numBytesInBuffer > 0 );
|
||||||
|
|
||||||
|
qDebug( "Writer::run: Trying to write %u bytes", numBytesInBuffer );
|
||||||
|
qint64 totalWritten = 0;
|
||||||
|
do {
|
||||||
|
mutex.unlock();
|
||||||
|
#ifdef Q_OS_WIN32
|
||||||
|
DWORD numWritten;
|
||||||
|
if ( !WriteFile( handle, buffer + totalWritten, numBytesInBuffer - totalWritten, &numWritten, 0 ) ) {
|
||||||
|
mutex.lock();
|
||||||
|
errorCode = static_cast<int>( GetLastError() );
|
||||||
|
qDebug( "Writer::run: got error code: %d", errorCode );
|
||||||
|
error = true;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
qint64 numWritten;
|
||||||
|
do {
|
||||||
|
numWritten = ::write( fd, buffer + totalWritten, numBytesInBuffer - totalWritten );
|
||||||
|
} while ( numWritten == -1 && errno == EINTR );
|
||||||
|
|
||||||
|
if ( numWritten < 0 ) {
|
||||||
|
mutex.lock();
|
||||||
|
errorCode = errno;
|
||||||
|
qDebug( "Writer::run: got error code: %d", errorCode );
|
||||||
|
error = true;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
totalWritten += numWritten;
|
||||||
|
mutex.lock();
|
||||||
|
} while ( totalWritten < numBytesInBuffer );
|
||||||
|
|
||||||
|
qDebug( "Writer::run: wrote %lld bytes", totalWritten );
|
||||||
|
|
||||||
|
numBytesInBuffer = 0;
|
||||||
|
bufferEmptyCondition.wakeAll();
|
||||||
|
emit bytesWritten( totalWritten );
|
||||||
|
}
|
||||||
|
leave:
|
||||||
|
qDebug( "Writer::run: terminating" );
|
||||||
|
numBytesInBuffer = 0;
|
||||||
|
bufferEmptyCondition.wakeAll();
|
||||||
|
emit bytesWritten( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
std::pair<KDPipeIODevice*,KDPipeIODevice*> KDPipeIODevice::makePairOfConnectedPipes() {
|
||||||
|
KDPipeIODevice * read = 0;
|
||||||
|
KDPipeIODevice * write = 0;
|
||||||
|
#ifdef Q_OS_WIN32
|
||||||
|
HANDLE rh;
|
||||||
|
HANDLE wh;
|
||||||
|
SECURITY_ATTRIBUTES sa;
|
||||||
|
memset( &sa, 0, sizeof(sa) );
|
||||||
|
sa.nLength = sizeof(sa);
|
||||||
|
sa.bInheritHandle = TRUE;
|
||||||
|
if ( CreatePipe( &rh, &wh, &sa, BUFFER_SIZE ) ) {
|
||||||
|
read = new KDPipeIODevice;
|
||||||
|
read->open( rh, ReadOnly );
|
||||||
|
write = new KDPipeIODevice;
|
||||||
|
write->open( wh, WriteOnly );
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
int fds[2];
|
||||||
|
if ( pipe( fds ) == 0 ) {
|
||||||
|
read = new KDPipeIODevice;
|
||||||
|
read->open( fds[0], ReadOnly );
|
||||||
|
write = new KDPipeIODevice;
|
||||||
|
write->open( fds[1], WriteOnly );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return std::make_pair( read, write );
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef KDAB_DEFINE_CHECKS
|
||||||
|
KDAB_DEFINE_CHECKS( KDPipeIODevice ) {
|
||||||
|
if ( !isOpen() ) {
|
||||||
|
assert( openMode() == NotOpen );
|
||||||
|
assert( !d->reader );
|
||||||
|
assert( !d->writer );
|
||||||
|
#ifdef Q_OS_WIN32
|
||||||
|
assert( !d->handle );
|
||||||
|
#else
|
||||||
|
assert( d->fd < 0 );
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
assert( openMode() != NotOpen );
|
||||||
|
assert( openMode() & ReadWrite );
|
||||||
|
if ( openMode() & ReadOnly ) {
|
||||||
|
assert( d->reader );
|
||||||
|
synchronized( d->reader )
|
||||||
|
assert( d->reader->eof || d->reader->error || d->reader->isRunning() );
|
||||||
|
}
|
||||||
|
if ( openMode() & WriteOnly ) {
|
||||||
|
assert( d->writer );
|
||||||
|
synchronized( d->writer )
|
||||||
|
assert( d->writer->error || d->writer->isRunning() );
|
||||||
|
}
|
||||||
|
#ifdef Q_OS_WIN32
|
||||||
|
assert( d->handle );
|
||||||
|
#else
|
||||||
|
assert( d->fd >= 0 );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // KDAB_DEFINE_CHECKS
|
||||||
|
|
||||||
|
#include "moc_kdpipeiodevice.cpp"
|
||||||
|
#include "kdpipeiodevice.moc"
|
66
gpgme/kdpipeiodevice.h
Normal file
66
gpgme/kdpipeiodevice.h
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2007 Klarälvdalens Datakonsult AB
|
||||||
|
|
||||||
|
KDPipeIODevice is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
KDPipeIODevice 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 Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public License
|
||||||
|
along with KDPipeIODevice; see the file COPYING.LIB. If not, write to the
|
||||||
|
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __KDTOOLSCORE_KDPIPEIODEVICE_H__
|
||||||
|
#define __KDTOOLSCORE_KDPIPEIODEVICE_H__
|
||||||
|
|
||||||
|
#include <QIODevice>
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
//#include "checker.h"
|
||||||
|
|
||||||
|
class KDPipeIODevice : public QIODevice {
|
||||||
|
Q_OBJECT
|
||||||
|
//KDAB_MAKE_CHECKABLE( KDPipeIODevice )
|
||||||
|
public:
|
||||||
|
explicit KDPipeIODevice( QObject * parent=0 );
|
||||||
|
explicit KDPipeIODevice( int fd, OpenMode=ReadOnly, QObject * parent=0 );
|
||||||
|
explicit KDPipeIODevice( Qt::HANDLE handle, OpenMode=ReadOnly, QObject * parent=0 );
|
||||||
|
~KDPipeIODevice();
|
||||||
|
|
||||||
|
static std::pair<KDPipeIODevice*, KDPipeIODevice*> makePairOfConnectedPipes();
|
||||||
|
|
||||||
|
bool open( int fd, OpenMode mode=ReadOnly );
|
||||||
|
bool open( Qt::HANDLE handle, OpenMode mode=ReadOnly );
|
||||||
|
|
||||||
|
Qt::HANDLE handle() const;
|
||||||
|
int descriptor() const;
|
||||||
|
|
||||||
|
/* reimp */ qint64 bytesAvailable() const;
|
||||||
|
/* reimp */ qint64 bytesToWrite() const;
|
||||||
|
/* reimp */ bool canReadLine() const;
|
||||||
|
/* reimp */ void close();
|
||||||
|
/* reimp */ bool isSequential() const;
|
||||||
|
/* reimp */ bool atEnd() const;
|
||||||
|
|
||||||
|
/* reimp */ bool waitForBytesWritten( int msecs );
|
||||||
|
/* reimp */ bool waitForReadyRead( int msecs );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/* reimp */ qint64 readData( char * data, qint64 maxSize );
|
||||||
|
/* reimp */ qint64 writeData( const char * data, qint64 maxSize );
|
||||||
|
|
||||||
|
private:
|
||||||
|
class Private;
|
||||||
|
Private * d;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __KDTOOLSCORE_KDPIPEIODEVICE_H__ */
|
||||||
|
|
132
gpgme/kdpipeiodevice.moc
Normal file
132
gpgme/kdpipeiodevice.moc
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
** Meta object code from reading C++ file 'kdpipeiodevice.cpp'
|
||||||
|
**
|
||||||
|
** Created: Mon Aug 27 15:17:18 2007
|
||||||
|
** by: The Qt Meta Object Compiler version 59 (Qt 4.3.0)
|
||||||
|
**
|
||||||
|
** WARNING! All changes made in this file will be lost!
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#if !defined(Q_MOC_OUTPUT_REVISION)
|
||||||
|
#error "The header file 'kdpipeiodevice.cpp' doesn't include <QObject>."
|
||||||
|
#elif Q_MOC_OUTPUT_REVISION != 59
|
||||||
|
#error "This file was generated using the moc from 4.3.0. It"
|
||||||
|
#error "cannot be used with the include files from this version of Qt."
|
||||||
|
#error "(The moc has changed too much.)"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static const uint qt_meta_data_Reader[] = {
|
||||||
|
|
||||||
|
// content:
|
||||||
|
1, // revision
|
||||||
|
0, // classname
|
||||||
|
0, 0, // classinfo
|
||||||
|
1, 10, // methods
|
||||||
|
0, 0, // properties
|
||||||
|
0, 0, // enums/sets
|
||||||
|
|
||||||
|
// signals: signature, parameters, type, tag, flags
|
||||||
|
8, 7, 7, 7, 0x05,
|
||||||
|
|
||||||
|
0 // eod
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char qt_meta_stringdata_Reader[] = {
|
||||||
|
"Reader\0\0readyRead()\0"
|
||||||
|
};
|
||||||
|
|
||||||
|
const QMetaObject Reader::staticMetaObject = {
|
||||||
|
{ &QThread::staticMetaObject, qt_meta_stringdata_Reader,
|
||||||
|
qt_meta_data_Reader, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
const QMetaObject *Reader::metaObject() const
|
||||||
|
{
|
||||||
|
return &staticMetaObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *Reader::qt_metacast(const char *_clname)
|
||||||
|
{
|
||||||
|
if (!_clname) return 0;
|
||||||
|
if (!strcmp(_clname, qt_meta_stringdata_Reader))
|
||||||
|
return static_cast<void*>(const_cast< Reader*>(this));
|
||||||
|
return QThread::qt_metacast(_clname);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Reader::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||||
|
{
|
||||||
|
_id = QThread::qt_metacall(_c, _id, _a);
|
||||||
|
if (_id < 0)
|
||||||
|
return _id;
|
||||||
|
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||||
|
switch (_id) {
|
||||||
|
case 0: readyRead(); break;
|
||||||
|
}
|
||||||
|
_id -= 1;
|
||||||
|
}
|
||||||
|
return _id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SIGNAL 0
|
||||||
|
void Reader::readyRead()
|
||||||
|
{
|
||||||
|
QMetaObject::activate(this, &staticMetaObject, 0, 0);
|
||||||
|
}
|
||||||
|
static const uint qt_meta_data_Writer[] = {
|
||||||
|
|
||||||
|
// content:
|
||||||
|
1, // revision
|
||||||
|
0, // classname
|
||||||
|
0, 0, // classinfo
|
||||||
|
1, 10, // methods
|
||||||
|
0, 0, // properties
|
||||||
|
0, 0, // enums/sets
|
||||||
|
|
||||||
|
// signals: signature, parameters, type, tag, flags
|
||||||
|
8, 7, 7, 7, 0x05,
|
||||||
|
|
||||||
|
0 // eod
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char qt_meta_stringdata_Writer[] = {
|
||||||
|
"Writer\0\0bytesWritten(qint64)\0"
|
||||||
|
};
|
||||||
|
|
||||||
|
const QMetaObject Writer::staticMetaObject = {
|
||||||
|
{ &QThread::staticMetaObject, qt_meta_stringdata_Writer,
|
||||||
|
qt_meta_data_Writer, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
const QMetaObject *Writer::metaObject() const
|
||||||
|
{
|
||||||
|
return &staticMetaObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *Writer::qt_metacast(const char *_clname)
|
||||||
|
{
|
||||||
|
if (!_clname) return 0;
|
||||||
|
if (!strcmp(_clname, qt_meta_stringdata_Writer))
|
||||||
|
return static_cast<void*>(const_cast< Writer*>(this));
|
||||||
|
return QThread::qt_metacast(_clname);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Writer::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||||
|
{
|
||||||
|
_id = QThread::qt_metacall(_c, _id, _a);
|
||||||
|
if (_id < 0)
|
||||||
|
return _id;
|
||||||
|
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||||
|
switch (_id) {
|
||||||
|
case 0: bytesWritten((*reinterpret_cast< qint64(*)>(_a[1]))); break;
|
||||||
|
}
|
||||||
|
_id -= 1;
|
||||||
|
}
|
||||||
|
return _id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SIGNAL 0
|
||||||
|
void Writer::bytesWritten(qint64 _t1)
|
||||||
|
{
|
||||||
|
void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
|
||||||
|
QMetaObject::activate(this, &staticMetaObject, 0, _a);
|
||||||
|
}
|
60
gpgme/moc_kdpipeiodevice.cpp
Normal file
60
gpgme/moc_kdpipeiodevice.cpp
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
** Meta object code from reading C++ file 'kdpipeiodevice.h'
|
||||||
|
**
|
||||||
|
** Created: Mon Aug 27 15:17:18 2007
|
||||||
|
** by: The Qt Meta Object Compiler version 59 (Qt 4.3.0)
|
||||||
|
**
|
||||||
|
** WARNING! All changes made in this file will be lost!
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "kdpipeiodevice.h"
|
||||||
|
#if !defined(Q_MOC_OUTPUT_REVISION)
|
||||||
|
#error "The header file 'kdpipeiodevice.h' doesn't include <QObject>."
|
||||||
|
#elif Q_MOC_OUTPUT_REVISION != 59
|
||||||
|
#error "This file was generated using the moc from 4.3.0. It"
|
||||||
|
#error "cannot be used with the include files from this version of Qt."
|
||||||
|
#error "(The moc has changed too much.)"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static const uint qt_meta_data_KDPipeIODevice[] = {
|
||||||
|
|
||||||
|
// content:
|
||||||
|
1, // revision
|
||||||
|
0, // classname
|
||||||
|
0, 0, // classinfo
|
||||||
|
0, 0, // methods
|
||||||
|
0, 0, // properties
|
||||||
|
0, 0, // enums/sets
|
||||||
|
|
||||||
|
0 // eod
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char qt_meta_stringdata_KDPipeIODevice[] = {
|
||||||
|
"KDPipeIODevice\0"
|
||||||
|
};
|
||||||
|
|
||||||
|
const QMetaObject KDPipeIODevice::staticMetaObject = {
|
||||||
|
{ &QIODevice::staticMetaObject, qt_meta_stringdata_KDPipeIODevice,
|
||||||
|
qt_meta_data_KDPipeIODevice, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
const QMetaObject *KDPipeIODevice::metaObject() const
|
||||||
|
{
|
||||||
|
return &staticMetaObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *KDPipeIODevice::qt_metacast(const char *_clname)
|
||||||
|
{
|
||||||
|
if (!_clname) return 0;
|
||||||
|
if (!strcmp(_clname, qt_meta_stringdata_KDPipeIODevice))
|
||||||
|
return static_cast<void*>(const_cast< KDPipeIODevice*>(this));
|
||||||
|
return QIODevice::qt_metacast(_clname);
|
||||||
|
}
|
||||||
|
|
||||||
|
int KDPipeIODevice::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||||
|
{
|
||||||
|
_id = QIODevice::qt_metacall(_c, _id, _a);
|
||||||
|
if (_id < 0)
|
||||||
|
return _id;
|
||||||
|
return _id;
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
/* posix-sema.c
|
/* posix-sema.c
|
||||||
Copyright (C) 2001 Werner Koch (dd9jn)
|
Copyright (C) 2001 Werner Koch (dd9jn)
|
||||||
Copyright (C) 2001, 2002, 2004 g10 Code GmbH
|
Copyright (C) 2001, 2002, 2004, 2007 g10 Code GmbH
|
||||||
|
|
||||||
This file is part of GPGME.
|
This file is part of GPGME.
|
||||||
|
|
||||||
@ -45,18 +45,18 @@ _gpgme_sema_subsystem_init ()
|
|||||||
void
|
void
|
||||||
_gpgme_sema_cs_enter (struct critsect_s *s)
|
_gpgme_sema_cs_enter (struct critsect_s *s)
|
||||||
{
|
{
|
||||||
_gpgme_ath_mutex_lock (&s->private);
|
_gpgme_ath_mutex_lock (&s->priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_gpgme_sema_cs_leave (struct critsect_s *s)
|
_gpgme_sema_cs_leave (struct critsect_s *s)
|
||||||
{
|
{
|
||||||
_gpgme_ath_mutex_unlock (&s->private);
|
_gpgme_ath_mutex_unlock (&s->priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_gpgme_sema_cs_destroy (struct critsect_s *s)
|
_gpgme_sema_cs_destroy (struct critsect_s *s)
|
||||||
{
|
{
|
||||||
_gpgme_ath_mutex_destroy (&s->private);
|
_gpgme_ath_mutex_destroy (&s->priv);
|
||||||
s->private = NULL;
|
s->priv = NULL;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* sema.h - Definitions for semaphores.
|
/* sema.h - Definitions for semaphores.
|
||||||
Copyright (C) 2000 Werner Koch (dd9jn)
|
Copyright (C) 2000 Werner Koch (dd9jn)
|
||||||
Copyright (C) 2001, 2003, 2004 g10 Code GmbH
|
Copyright (C) 2001, 2003, 2004, 2007 g10 Code GmbH
|
||||||
|
|
||||||
This file is part of GPGME.
|
This file is part of GPGME.
|
||||||
|
|
||||||
@ -25,7 +25,7 @@
|
|||||||
struct critsect_s
|
struct critsect_s
|
||||||
{
|
{
|
||||||
const char *name;
|
const char *name;
|
||||||
void *private;
|
void *priv;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DEFINE_GLOBAL_LOCK(name) \
|
#define DEFINE_GLOBAL_LOCK(name) \
|
||||||
@ -39,7 +39,7 @@ struct critsect_s
|
|||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
(a).name = #a; \
|
(a).name = #a; \
|
||||||
(a).private = NULL; \
|
(a).priv = NULL; \
|
||||||
} \
|
} \
|
||||||
while (0)
|
while (0)
|
||||||
#define DESTROY_LOCK(name) _gpgme_sema_cs_destroy (&(name))
|
#define DESTROY_LOCK(name) _gpgme_sema_cs_destroy (&(name))
|
||||||
|
@ -97,14 +97,23 @@ find_channel (int fd, int create)
|
|||||||
return giochannel_table[fd];
|
return giochannel_table[fd];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Look up the giochannel for "file descriptor" FD. */
|
|
||||||
GIOChannel *
|
/* Compatibility interface. Obsolete. */
|
||||||
|
void *
|
||||||
gpgme_get_giochannel (int fd)
|
gpgme_get_giochannel (int fd)
|
||||||
{
|
{
|
||||||
return find_channel (fd, 0);
|
return find_channel (fd, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Look up the giochannel for "file descriptor" FD. */
|
||||||
|
void *
|
||||||
|
gpgme_get_fdptr (int fd)
|
||||||
|
{
|
||||||
|
return find_channel (fd, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Write the printable version of FD to the buffer BUF of length
|
/* Write the printable version of FD to the buffer BUF of length
|
||||||
BUFLEN. The printable version is the representation on the command
|
BUFLEN. The printable version is the representation on the command
|
||||||
line that the child process expects. */
|
line that the child process expects. */
|
||||||
|
@ -1403,9 +1403,9 @@ _gpgme_io_dup (int fd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* The following interface is only useful for GPGME Glib. */
|
/* The following interface is only useful for GPGME Glib and Qt. */
|
||||||
|
|
||||||
/* Look up the giochannel for file descriptor FD. */
|
/* Compatibility interface, obsolete. */
|
||||||
void *
|
void *
|
||||||
gpgme_get_giochannel (int fd)
|
gpgme_get_giochannel (int fd)
|
||||||
{
|
{
|
||||||
@ -1413,3 +1413,9 @@ gpgme_get_giochannel (int fd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Look up the giochannel or qiodevice for file descriptor FD. */
|
||||||
|
void *
|
||||||
|
gpgme_get_fdptr (int fd)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
609
gpgme/w32-qt-io.cpp
Normal file
609
gpgme/w32-qt-io.cpp
Normal file
@ -0,0 +1,609 @@
|
|||||||
|
/* w32-glib-io.c - W32 Glib I/O functions
|
||||||
|
Copyright (C) 2000 Werner Koch (dd9jn)
|
||||||
|
Copyright (C) 2001, 2002, 2004, 2005, 2007 g10 Code GmbH
|
||||||
|
|
||||||
|
This file is part of GPGME.
|
||||||
|
|
||||||
|
GPGME 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.
|
||||||
|
|
||||||
|
GPGME 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, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
02111-1307, USA. */
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#include <io.h>
|
||||||
|
|
||||||
|
#include "kdpipeiodevice.h"
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#include "util.h"
|
||||||
|
#include "priv-io.h"
|
||||||
|
#include "sema.h"
|
||||||
|
#include "debug.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef O_BINARY
|
||||||
|
#ifdef _O_BINARY
|
||||||
|
#define O_BINARY _O_BINARY
|
||||||
|
#else
|
||||||
|
#define O_BINARY 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* This file is an ugly hack to get GPGME working with Qt on Windows
|
||||||
|
targets. On Windows, you can not select() on file descriptors.
|
||||||
|
The only way to check if there is something to read is to read
|
||||||
|
something. This means that GPGME can not let Qt check for data
|
||||||
|
without letting Qt also handle the data on Windows targets.
|
||||||
|
|
||||||
|
The ugly consequence is that we need to work on QIODevices in
|
||||||
|
GPGME, creating a Qt dependency. Also, we need to export an
|
||||||
|
interface for the application to get at GPGME's QIODevices. There
|
||||||
|
is no good way to abstract all this with callbacks, because the
|
||||||
|
whole thing is also interconnected with the creation of pipes and
|
||||||
|
child processes.
|
||||||
|
|
||||||
|
The following rule applies only to this I/O backend:
|
||||||
|
|
||||||
|
* ALL operations must use the user defined event loop. GPGME can
|
||||||
|
not anymore provide its own event loop. This is mostly a sanity
|
||||||
|
requirement: Although we have in theory all information we need to
|
||||||
|
make the GPGME W32 code for select still work, it would be a big
|
||||||
|
complication and require changes throughout GPGME.
|
||||||
|
|
||||||
|
Eventually, we probably have to bite the bullet and make some
|
||||||
|
really nice callback interfaces to let the user control all this at
|
||||||
|
a per-context level. */
|
||||||
|
|
||||||
|
|
||||||
|
#define MAX_SLAFD 256
|
||||||
|
|
||||||
|
QIODevice *iodevice_table[MAX_SLAFD];
|
||||||
|
|
||||||
|
|
||||||
|
static QIODevice *
|
||||||
|
find_channel (int fd, int create)
|
||||||
|
{
|
||||||
|
if (fd < 0 || fd >= MAX_SLAFD)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (create && !iodevice_table[fd])
|
||||||
|
iodevice_table[fd] = new KDPipeIODevice
|
||||||
|
(fd, QIODevice::ReadOnly|QIODevice::Unbuffered);
|
||||||
|
|
||||||
|
return iodevice_table[fd];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Write the printable version of FD to the buffer BUF of length
|
||||||
|
BUFLEN. The printable version is the representation on the command
|
||||||
|
line that the child process expects. */
|
||||||
|
int
|
||||||
|
_gpgme_io_fd2str (char *buf, int buflen, int fd)
|
||||||
|
{
|
||||||
|
return snprintf (buf, buflen, "%ld", (long) _get_osfhandle (fd));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
_gpgme_io_subsystem_init (void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct
|
||||||
|
{
|
||||||
|
_gpgme_close_notify_handler_t handler;
|
||||||
|
void *value;
|
||||||
|
} notify_table[MAX_SLAFD];
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
_gpgme_io_read (int fd, void *buffer, size_t count)
|
||||||
|
{
|
||||||
|
int saved_errno = 0;
|
||||||
|
qint64 nread;
|
||||||
|
QIODevice *chan;
|
||||||
|
TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_read", fd,
|
||||||
|
"buffer=%p, count=%u", buffer, count);
|
||||||
|
|
||||||
|
chan = find_channel (fd, 0);
|
||||||
|
if (!chan)
|
||||||
|
{
|
||||||
|
TRACE_LOG ("no channel registered");
|
||||||
|
errno = EINVAL;
|
||||||
|
return TRACE_SYSRES (-1);
|
||||||
|
}
|
||||||
|
TRACE_LOG1 ("channel %p", chan);
|
||||||
|
|
||||||
|
{
|
||||||
|
// GError *err = NULL;
|
||||||
|
// status = g_io_channel_read_chars (chan, (gchar *) buffer,
|
||||||
|
// count, &nread, &err);
|
||||||
|
nread = chan->read( buffer, count );
|
||||||
|
if ( nread < 0 ) {
|
||||||
|
TRACE_LOG1 ("err %s", qPrintable( chan->errorString() ) );
|
||||||
|
saved_errno = EIO;
|
||||||
|
nread = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE_LOGBUF (buffer, nread);
|
||||||
|
|
||||||
|
errno = saved_errno;
|
||||||
|
return TRACE_SYSRES (nread);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
_gpgme_io_write (int fd, const void *buffer, size_t count)
|
||||||
|
{
|
||||||
|
qint64 nwritten;
|
||||||
|
QIODevice *chan;
|
||||||
|
TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_write", fd,
|
||||||
|
"buffer=%p, count=%u", buffer, count);
|
||||||
|
TRACE_LOGBUF (buffer, count);
|
||||||
|
|
||||||
|
chan = find_channel (fd, 0);
|
||||||
|
if (!chan)
|
||||||
|
{
|
||||||
|
TRACE_LOG ("fd %d: no channel registered");
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
nwritten = chan->write( buffer, count );
|
||||||
|
|
||||||
|
if (nwritten < 0)
|
||||||
|
{
|
||||||
|
nwritten = -1;
|
||||||
|
errno = EIO;
|
||||||
|
return TRACE_SYSRES(-1)
|
||||||
|
}
|
||||||
|
errno = 0;
|
||||||
|
return TRACE_SYSRES (nwritten);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
_gpgme_io_pipe (int filedes[2], int inherit_idx)
|
||||||
|
{
|
||||||
|
QIODevice *chan;
|
||||||
|
TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_pipe", filedes,
|
||||||
|
"inherit_idx=%i (GPGME uses it for %s)",
|
||||||
|
inherit_idx, inherit_idx ? "writing" : "reading");
|
||||||
|
|
||||||
|
#define PIPEBUF_SIZE 4096
|
||||||
|
if (_pipe (filedes, PIPEBUF_SIZE, O_NOINHERIT | O_BINARY) == -1)
|
||||||
|
return TRACE_SYSRES (-1);
|
||||||
|
|
||||||
|
/* Make one end inheritable. */
|
||||||
|
if (inherit_idx == 0)
|
||||||
|
{
|
||||||
|
int new_read;
|
||||||
|
|
||||||
|
new_read = _dup (filedes[0]);
|
||||||
|
_close (filedes[0]);
|
||||||
|
filedes[0] = new_read;
|
||||||
|
|
||||||
|
if (new_read < 0)
|
||||||
|
{
|
||||||
|
_close (filedes[1]);
|
||||||
|
return TRACE_SYSRES (-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (inherit_idx == 1)
|
||||||
|
{
|
||||||
|
int new_write;
|
||||||
|
|
||||||
|
new_write = _dup (filedes[1]);
|
||||||
|
_close (filedes[1]);
|
||||||
|
filedes[1] = new_write;
|
||||||
|
|
||||||
|
if (new_write < 0)
|
||||||
|
{
|
||||||
|
_close (filedes[0]);
|
||||||
|
return TRACE_SYSRES (-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now we have a pipe with the right end inheritable. The other end
|
||||||
|
should have a giochannel. */
|
||||||
|
chan = find_channel (filedes[1 - inherit_idx], 1);
|
||||||
|
if (!chan)
|
||||||
|
{
|
||||||
|
int saved_errno = errno;
|
||||||
|
_close (filedes[0]);
|
||||||
|
_close (filedes[1]);
|
||||||
|
errno = saved_errno;
|
||||||
|
return TRACE_SYSRES (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRACE_SUC5 ("read=0x%x/%p, write=0x%x/%p, channel=%p",
|
||||||
|
filedes[0], (HANDLE) _get_osfhandle (filedes[0]),
|
||||||
|
filedes[1], (HANDLE) _get_osfhandle (filedes[1]),
|
||||||
|
chan);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
_gpgme_io_close (int fd)
|
||||||
|
{
|
||||||
|
QIODevice *chan;
|
||||||
|
TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_close", fd);
|
||||||
|
|
||||||
|
if (fd < 0 || fd >= MAX_SLAFD)
|
||||||
|
{
|
||||||
|
errno = EBADF;
|
||||||
|
return TRACE_SYSRES (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* First call the notify handler. */
|
||||||
|
if (notify_table[fd].handler)
|
||||||
|
{
|
||||||
|
notify_table[fd].handler (fd, notify_table[fd].value);
|
||||||
|
notify_table[fd].handler = NULL;
|
||||||
|
notify_table[fd].value = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Then do the close. */
|
||||||
|
chan = iodevice_table[fd];
|
||||||
|
if (chan)
|
||||||
|
{
|
||||||
|
chan->close();
|
||||||
|
delete chan;
|
||||||
|
iodevice_table[fd] = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_close (fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
_gpgme_io_set_close_notify (int fd, _gpgme_close_notify_handler_t handler,
|
||||||
|
void *value)
|
||||||
|
{
|
||||||
|
TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_set_close_notify", fd,
|
||||||
|
"close_handler=%p/%p", handler, value);
|
||||||
|
|
||||||
|
assert (fd != -1);
|
||||||
|
|
||||||
|
if (fd < 0 || fd >= (int) DIM (notify_table))
|
||||||
|
{
|
||||||
|
errno = EINVAL;
|
||||||
|
return TRACE_SYSRES (-1);
|
||||||
|
}
|
||||||
|
notify_table[fd].handler = handler;
|
||||||
|
notify_table[fd].value = value;
|
||||||
|
return TRACE_SYSRES (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
_gpgme_io_set_nonblocking (int fd)
|
||||||
|
{
|
||||||
|
/* Qt always uses non-blocking IO, except for files, maybe, but who
|
||||||
|
uses that? */
|
||||||
|
TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_set_nonblocking", fd);
|
||||||
|
|
||||||
|
return TRACE_SYSRES (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char *
|
||||||
|
build_commandline (char **argv)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int n = 0;
|
||||||
|
char *buf;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
/* We have to quote some things because under Windows the program
|
||||||
|
parses the commandline and does some unquoting. We enclose the
|
||||||
|
whole argument in double-quotes, and escape literal double-quotes
|
||||||
|
as well as backslashes with a backslash. We end up with a
|
||||||
|
trailing space at the end of the line, but that is harmless. */
|
||||||
|
for (i = 0; argv[i]; i++)
|
||||||
|
{
|
||||||
|
p = argv[i];
|
||||||
|
/* The leading double-quote. */
|
||||||
|
n++;
|
||||||
|
while (*p)
|
||||||
|
{
|
||||||
|
/* An extra one for each literal that must be escaped. */
|
||||||
|
if (*p == '\\' || *p == '"')
|
||||||
|
n++;
|
||||||
|
n++;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
/* The trailing double-quote and the delimiter. */
|
||||||
|
n += 2;
|
||||||
|
}
|
||||||
|
/* And a trailing zero. */
|
||||||
|
n++;
|
||||||
|
|
||||||
|
buf = p = malloc (n);
|
||||||
|
if (!buf)
|
||||||
|
return NULL;
|
||||||
|
for (i = 0; argv[i]; i++)
|
||||||
|
{
|
||||||
|
char *argvp = argv[i];
|
||||||
|
|
||||||
|
*(p++) = '"';
|
||||||
|
while (*argvp)
|
||||||
|
{
|
||||||
|
if (*argvp == '\\' || *argvp == '"')
|
||||||
|
*(p++) = '\\';
|
||||||
|
*(p++) = *(argvp++);
|
||||||
|
}
|
||||||
|
*(p++) = '"';
|
||||||
|
*(p++) = ' ';
|
||||||
|
}
|
||||||
|
*(p++) = 0;
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
_gpgme_io_spawn (const char *path, char **argv,
|
||||||
|
struct spawn_fd_item_s *fd_child_list,
|
||||||
|
struct spawn_fd_item_s *fd_parent_list)
|
||||||
|
{
|
||||||
|
SECURITY_ATTRIBUTES sec_attr;
|
||||||
|
PROCESS_INFORMATION pi =
|
||||||
|
{
|
||||||
|
NULL, /* returns process handle */
|
||||||
|
0, /* returns primary thread handle */
|
||||||
|
0, /* returns pid */
|
||||||
|
0 /* returns tid */
|
||||||
|
};
|
||||||
|
STARTUPINFO si;
|
||||||
|
char *envblock = NULL;
|
||||||
|
int cr_flags = CREATE_DEFAULT_ERROR_MODE
|
||||||
|
| GetPriorityClass (GetCurrentProcess ());
|
||||||
|
int i;
|
||||||
|
char *arg_string;
|
||||||
|
int duped_stdin = 0;
|
||||||
|
int duped_stderr = 0;
|
||||||
|
HANDLE hnul = INVALID_HANDLE_VALUE;
|
||||||
|
/* FIXME. */
|
||||||
|
int debug_me = 0;
|
||||||
|
TRACE_BEG1 (DEBUG_SYSIO, "_gpgme_io_spawn", path,
|
||||||
|
"path=%s", path);
|
||||||
|
i = 0;
|
||||||
|
while (argv[i])
|
||||||
|
{
|
||||||
|
TRACE_LOG2 ("argv[%2i] = %s", i, argv[i]);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset (&sec_attr, 0, sizeof sec_attr);
|
||||||
|
sec_attr.nLength = sizeof sec_attr;
|
||||||
|
sec_attr.bInheritHandle = FALSE;
|
||||||
|
|
||||||
|
arg_string = build_commandline (argv);
|
||||||
|
if (!arg_string)
|
||||||
|
return TRACE_SYSRES (-1);
|
||||||
|
|
||||||
|
memset (&si, 0, sizeof si);
|
||||||
|
si.cb = sizeof (si);
|
||||||
|
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
|
||||||
|
si.wShowWindow = debug_me? SW_SHOW : SW_HIDE;
|
||||||
|
si.hStdInput = GetStdHandle (STD_INPUT_HANDLE);
|
||||||
|
si.hStdOutput = GetStdHandle (STD_OUTPUT_HANDLE);
|
||||||
|
si.hStdError = GetStdHandle (STD_ERROR_HANDLE);
|
||||||
|
|
||||||
|
for (i = 0; fd_child_list[i].fd != -1; i++)
|
||||||
|
{
|
||||||
|
if (fd_child_list[i].dup_to == 0)
|
||||||
|
{
|
||||||
|
si.hStdInput = (HANDLE) _get_osfhandle (fd_child_list[i].fd);
|
||||||
|
TRACE_LOG2 ("using 0x%x/%p for stdin", fd_child_list[i].fd,
|
||||||
|
_get_osfhandle (fd_child_list[i].fd));
|
||||||
|
duped_stdin = 1;
|
||||||
|
}
|
||||||
|
else if (fd_child_list[i].dup_to == 1)
|
||||||
|
{
|
||||||
|
si.hStdOutput = (HANDLE) _get_osfhandle (fd_child_list[i].fd);
|
||||||
|
TRACE_LOG2 ("using 0x%x/%p for stdout", fd_child_list[i].fd,
|
||||||
|
_get_osfhandle (fd_child_list[i].fd));
|
||||||
|
}
|
||||||
|
else if (fd_child_list[i].dup_to == 2)
|
||||||
|
{
|
||||||
|
si.hStdError = (HANDLE) _get_osfhandle (fd_child_list[i].fd);
|
||||||
|
TRACE_LOG2 ("using 0x%x/%p for stderr", fd_child_list[i].fd,
|
||||||
|
_get_osfhandle (fd_child_list[i].fd));
|
||||||
|
duped_stderr = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!duped_stdin || !duped_stderr)
|
||||||
|
{
|
||||||
|
SECURITY_ATTRIBUTES sa;
|
||||||
|
|
||||||
|
memset (&sa, 0, sizeof sa);
|
||||||
|
sa.nLength = sizeof sa;
|
||||||
|
sa.bInheritHandle = TRUE;
|
||||||
|
hnul = CreateFile ("nul",
|
||||||
|
GENERIC_READ|GENERIC_WRITE,
|
||||||
|
FILE_SHARE_READ|FILE_SHARE_WRITE,
|
||||||
|
&sa,
|
||||||
|
OPEN_EXISTING,
|
||||||
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
|
NULL);
|
||||||
|
if (hnul == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
TRACE_LOG1 ("CreateFile (\"nul\") failed: ec=%d",
|
||||||
|
(int) GetLastError ());
|
||||||
|
free (arg_string);
|
||||||
|
/* FIXME: Should translate the error code. */
|
||||||
|
errno = EIO;
|
||||||
|
return TRACE_SYSRES (-1);
|
||||||
|
}
|
||||||
|
/* Make sure that the process has a connected stdin. */
|
||||||
|
if (!duped_stdin)
|
||||||
|
{
|
||||||
|
si.hStdInput = hnul;
|
||||||
|
TRACE_LOG1 ("using 0x%x for dummy stdin", (int) hnul);
|
||||||
|
}
|
||||||
|
/* We normally don't want all the normal output. */
|
||||||
|
if (!duped_stderr)
|
||||||
|
{
|
||||||
|
si.hStdError = hnul;
|
||||||
|
TRACE_LOG1 ("using %d for dummy stderr", (int)hnul);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cr_flags |= CREATE_SUSPENDED;
|
||||||
|
cr_flags |= DETACHED_PROCESS;
|
||||||
|
if (!CreateProcessA (path,
|
||||||
|
arg_string,
|
||||||
|
&sec_attr, /* process security attributes */
|
||||||
|
&sec_attr, /* thread security attributes */
|
||||||
|
TRUE, /* inherit handles */
|
||||||
|
cr_flags, /* creation flags */
|
||||||
|
envblock, /* environment */
|
||||||
|
NULL, /* use current drive/directory */
|
||||||
|
&si, /* startup information */
|
||||||
|
&pi)) /* returns process information */
|
||||||
|
{
|
||||||
|
TRACE_LOG1 ("CreateProcess failed: ec=%d", (int) GetLastError ());
|
||||||
|
free (arg_string);
|
||||||
|
/* FIXME: Should translate the error code. */
|
||||||
|
errno = EIO;
|
||||||
|
return TRACE_SYSRES (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Close the /dev/nul handle if used. */
|
||||||
|
if (hnul != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
if (!CloseHandle (hnul))
|
||||||
|
TRACE_LOG1 ("CloseHandle (hnul) failed: ec=%d (ignored)",
|
||||||
|
(int) GetLastError ());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Close the other ends of the pipes. */
|
||||||
|
for (i = 0; fd_parent_list[i].fd != -1; i++)
|
||||||
|
_gpgme_io_close (fd_parent_list[i].fd);
|
||||||
|
|
||||||
|
TRACE_LOG4 ("CreateProcess ready: hProcess=%p, hThread=%p, "
|
||||||
|
"dwProcessID=%d, dwThreadId=%d",
|
||||||
|
pi.hProcess, pi.hThread,
|
||||||
|
(int) pi.dwProcessId, (int) pi.dwThreadId);
|
||||||
|
|
||||||
|
if (ResumeThread (pi.hThread) < 0)
|
||||||
|
TRACE_LOG1 ("ResumeThread failed: ec=%d", (int) GetLastError ());
|
||||||
|
|
||||||
|
if (!CloseHandle (pi.hThread))
|
||||||
|
TRACE_LOG1 ("CloseHandle of thread failed: ec=%d",
|
||||||
|
(int) GetLastError ());
|
||||||
|
|
||||||
|
TRACE_SUC1 ("process=%p", pi.hProcess);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Select on the list of fds. Returns: -1 = error, 0 = timeout or
|
||||||
|
nothing to select, > 0 = number of signaled fds. */
|
||||||
|
int
|
||||||
|
_gpgme_io_select (struct io_select_fd_s *fds, size_t nfds, int nonblock)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int count;
|
||||||
|
/* Use a 1s timeout. */
|
||||||
|
|
||||||
|
void *dbg_help = NULL;
|
||||||
|
TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_select", fds,
|
||||||
|
"nfds=%u, nonblock=%u", nfds, nonblock);
|
||||||
|
|
||||||
|
// we only implement the special case of nonblock == true
|
||||||
|
assert( nonblock );
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
|
||||||
|
TRACE_SEQ (dbg_help, "select on [ ");
|
||||||
|
for (i = 0; i < nfds; i++)
|
||||||
|
{
|
||||||
|
if (fds[i].fd == -1)
|
||||||
|
{
|
||||||
|
fds[i].signaled = 0;
|
||||||
|
}
|
||||||
|
else if (fds[i].frozen)
|
||||||
|
{
|
||||||
|
TRACE_ADD1 (dbg_help, "f0x%x ", fds[i].fd);
|
||||||
|
fds[i].signaled = 0;
|
||||||
|
}
|
||||||
|
else if (fds[i].for_read )
|
||||||
|
{
|
||||||
|
const QIODevice * const chan = find_channel (fds[i].fd, 0);
|
||||||
|
assert (chan);
|
||||||
|
fds[i].signaled = chan->bytesAvailable() > 0 ? 1 : 0 ;
|
||||||
|
TRACE_ADD1 (dbg_help, "w0x%x ", fds[i].fd);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
else if (fds[i].for_write)
|
||||||
|
{
|
||||||
|
const QIODevice * const chan = find_channel (fds[i].fd, 0);
|
||||||
|
assert (chan);
|
||||||
|
fds[i].signaled = chan->bytesToWrite() > 0 ? 0 : 1 ;
|
||||||
|
TRACE_ADD1 (dbg_help, "w0x%x ", fds[i].fd);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TRACE_END (dbg_help, "]");
|
||||||
|
|
||||||
|
return TRACE_SYSRES (count);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
_gpgme_io_dup (int fd)
|
||||||
|
{
|
||||||
|
return _dup (fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Look up the qiodevice for file descriptor FD. */
|
||||||
|
extern "C"
|
||||||
|
void *
|
||||||
|
gpgme_get_fdptr (int fd)
|
||||||
|
{
|
||||||
|
return find_channel (fd, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Obsolete compatibility interface. */
|
||||||
|
extern "C"
|
||||||
|
void *
|
||||||
|
gpgme_get_giochannel (int fd)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
/* w32-sema.c
|
/* w32-sema.c
|
||||||
Copyright (C) 2001 Werner Koch (dd9jn)
|
Copyright (C) 2001 Werner Koch (dd9jn)
|
||||||
Copyright (C) 2001, 2002, 2004 g10 Code GmbH
|
Copyright (C) 2001, 2002, 2004, 2007 g10 Code GmbH
|
||||||
|
|
||||||
This file is part of GPGME.
|
This file is part of GPGME.
|
||||||
|
|
||||||
@ -65,7 +65,7 @@ critsect_init (struct critsect_s *s)
|
|||||||
|
|
||||||
/* first test whether it is really not initialized */
|
/* first test whether it is really not initialized */
|
||||||
EnterCriticalSection (&init_lock);
|
EnterCriticalSection (&init_lock);
|
||||||
if ( s->private ) {
|
if ( s->priv ) {
|
||||||
LeaveCriticalSection (&init_lock);
|
LeaveCriticalSection (&init_lock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -76,7 +76,7 @@ critsect_init (struct critsect_s *s)
|
|||||||
sema_fatal ("out of core while creating critical section lock");
|
sema_fatal ("out of core while creating critical section lock");
|
||||||
}
|
}
|
||||||
InitializeCriticalSection (mp);
|
InitializeCriticalSection (mp);
|
||||||
s->private = mp;
|
s->priv = mp;
|
||||||
LeaveCriticalSection (&init_lock);
|
LeaveCriticalSection (&init_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,25 +91,25 @@ _gpgme_sema_subsystem_init ()
|
|||||||
void
|
void
|
||||||
_gpgme_sema_cs_enter ( struct critsect_s *s )
|
_gpgme_sema_cs_enter ( struct critsect_s *s )
|
||||||
{
|
{
|
||||||
if (!s->private)
|
if (!s->priv)
|
||||||
critsect_init (s);
|
critsect_init (s);
|
||||||
EnterCriticalSection ( (CRITICAL_SECTION*)s->private );
|
EnterCriticalSection ( (CRITICAL_SECTION*)s->priv );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_gpgme_sema_cs_leave (struct critsect_s *s)
|
_gpgme_sema_cs_leave (struct critsect_s *s)
|
||||||
{
|
{
|
||||||
if (!s->private)
|
if (!s->priv)
|
||||||
critsect_init (s);
|
critsect_init (s);
|
||||||
LeaveCriticalSection ((CRITICAL_SECTION*)s->private);
|
LeaveCriticalSection ((CRITICAL_SECTION*)s->priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_gpgme_sema_cs_destroy ( struct critsect_s *s )
|
_gpgme_sema_cs_destroy ( struct critsect_s *s )
|
||||||
{
|
{
|
||||||
if (s && s->private) {
|
if (s && s->priv) {
|
||||||
DeleteCriticalSection ((CRITICAL_SECTION*)s->private);
|
DeleteCriticalSection ((CRITICAL_SECTION*)s->priv);
|
||||||
free (s->private);
|
free (s->priv);
|
||||||
s->private = NULL;
|
s->priv = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
157
m4/pkg.m4
Normal file
157
m4/pkg.m4
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
|
||||||
|
#
|
||||||
|
# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
# General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
#
|
||||||
|
# As a special exception to the GNU General Public License, if you
|
||||||
|
# distribute this file as part of a program that contains a
|
||||||
|
# configuration script generated by Autoconf, you may include it under
|
||||||
|
# the same distribution terms that you use for the rest of that program.
|
||||||
|
|
||||||
|
# PKG_PROG_PKG_CONFIG([MIN-VERSION])
|
||||||
|
# ----------------------------------
|
||||||
|
AC_DEFUN([PKG_PROG_PKG_CONFIG],
|
||||||
|
[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
|
||||||
|
m4_pattern_allow([^PKG_CONFIG(_PATH)?$])
|
||||||
|
AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl
|
||||||
|
if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
|
||||||
|
AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
|
||||||
|
fi
|
||||||
|
if test -n "$PKG_CONFIG"; then
|
||||||
|
_pkg_min_version=m4_default([$1], [0.9.0])
|
||||||
|
AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
|
||||||
|
if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
|
||||||
|
AC_MSG_RESULT([yes])
|
||||||
|
else
|
||||||
|
AC_MSG_RESULT([no])
|
||||||
|
PKG_CONFIG=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
fi[]dnl
|
||||||
|
])# PKG_PROG_PKG_CONFIG
|
||||||
|
|
||||||
|
# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
||||||
|
#
|
||||||
|
# Check to see whether a particular set of modules exists. Similar
|
||||||
|
# to PKG_CHECK_MODULES(), but does not set variables or print errors.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Similar to PKG_CHECK_MODULES, make sure that the first instance of
|
||||||
|
# this or PKG_CHECK_MODULES is called, or make sure to call
|
||||||
|
# PKG_CHECK_EXISTS manually
|
||||||
|
# --------------------------------------------------------------
|
||||||
|
AC_DEFUN([PKG_CHECK_EXISTS],
|
||||||
|
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
||||||
|
if test -n "$PKG_CONFIG" && \
|
||||||
|
AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
|
||||||
|
m4_ifval([$2], [$2], [:])
|
||||||
|
m4_ifvaln([$3], [else
|
||||||
|
$3])dnl
|
||||||
|
fi])
|
||||||
|
|
||||||
|
|
||||||
|
# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
|
||||||
|
# ---------------------------------------------
|
||||||
|
m4_define([_PKG_CONFIG],
|
||||||
|
[if test -n "$PKG_CONFIG"; then
|
||||||
|
if test -n "$$1"; then
|
||||||
|
pkg_cv_[]$1="$$1"
|
||||||
|
else
|
||||||
|
PKG_CHECK_EXISTS([$3],
|
||||||
|
[pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
|
||||||
|
[pkg_failed=yes])
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
pkg_failed=untried
|
||||||
|
fi[]dnl
|
||||||
|
])# _PKG_CONFIG
|
||||||
|
|
||||||
|
# _PKG_SHORT_ERRORS_SUPPORTED
|
||||||
|
# -----------------------------
|
||||||
|
AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
|
||||||
|
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
|
||||||
|
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
||||||
|
_pkg_short_errors_supported=yes
|
||||||
|
else
|
||||||
|
_pkg_short_errors_supported=no
|
||||||
|
fi[]dnl
|
||||||
|
])# _PKG_SHORT_ERRORS_SUPPORTED
|
||||||
|
|
||||||
|
|
||||||
|
# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
|
||||||
|
# [ACTION-IF-NOT-FOUND])
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Note that if there is a possibility the first call to
|
||||||
|
# PKG_CHECK_MODULES might not happen, you should be sure to include an
|
||||||
|
# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# --------------------------------------------------------------
|
||||||
|
AC_DEFUN([PKG_CHECK_MODULES],
|
||||||
|
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
||||||
|
AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
|
||||||
|
AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
|
||||||
|
|
||||||
|
pkg_failed=no
|
||||||
|
AC_MSG_CHECKING([for $1])
|
||||||
|
|
||||||
|
_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
|
||||||
|
_PKG_CONFIG([$1][_LIBS], [libs], [$2])
|
||||||
|
|
||||||
|
m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
|
||||||
|
and $1[]_LIBS to avoid the need to call pkg-config.
|
||||||
|
See the pkg-config man page for more details.])
|
||||||
|
|
||||||
|
if test $pkg_failed = yes; then
|
||||||
|
_PKG_SHORT_ERRORS_SUPPORTED
|
||||||
|
if test $_pkg_short_errors_supported = yes; then
|
||||||
|
$1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"`
|
||||||
|
else
|
||||||
|
$1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"`
|
||||||
|
fi
|
||||||
|
# Put the nasty error message in config.log where it belongs
|
||||||
|
echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
|
||||||
|
|
||||||
|
ifelse([$4], , [AC_MSG_ERROR(dnl
|
||||||
|
[Package requirements ($2) were not met:
|
||||||
|
|
||||||
|
$$1_PKG_ERRORS
|
||||||
|
|
||||||
|
Consider adjusting the PKG_CONFIG_PATH environment variable if you
|
||||||
|
installed software in a non-standard prefix.
|
||||||
|
|
||||||
|
_PKG_TEXT
|
||||||
|
])],
|
||||||
|
[AC_MSG_RESULT([no])
|
||||||
|
$4])
|
||||||
|
elif test $pkg_failed = untried; then
|
||||||
|
ifelse([$4], , [AC_MSG_FAILURE(dnl
|
||||||
|
[The pkg-config script could not be found or is too old. Make sure it
|
||||||
|
is in your PATH or set the PKG_CONFIG environment variable to the full
|
||||||
|
path to pkg-config.
|
||||||
|
|
||||||
|
_PKG_TEXT
|
||||||
|
|
||||||
|
To get pkg-config, see <http://www.freedesktop.org/software/pkgconfig>.])],
|
||||||
|
[$4])
|
||||||
|
else
|
||||||
|
$1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
|
||||||
|
$1[]_LIBS=$pkg_cv_[]$1[]_LIBS
|
||||||
|
AC_MSG_RESULT([yes])
|
||||||
|
ifelse([$3], , :, [$3])
|
||||||
|
fi[]dnl
|
||||||
|
])# PKG_CHECK_MODULES
|
Loading…
Reference in New Issue
Block a user