2009-10-20 Marcus Brinkmann <marcus@g10code.de>
* configure.ac: Replace internal libassuan by external libassuan. * m4/libassuan.m4: New file. * Makefile.am (assuan): Remove variable. (SUBDIRS): Remove ${assuan}. * assuan/: Removed. src/ 2009-10-20 Marcus Brinkmann <marcus@g10code.de> * Makefile.am (assuan_cppflags, assuan_libobjs): Removed. (gpgsm_components): Move engine-assuan.c to ... (assuan_components): ... this new variable. (main_sources): Add this new variable. (AM_CPPFLAGS): Remove $(assuan_cppflags). (AM_CFLAGS): Add @LIBASSUAN_CFLAGS@. (libgpgme_la_DEPENDENCIES, libgpgme_pth_la_DEPENDENCIES) (libgpgme_glib_la_DEPENDENCIES, libgpgme_qt_la_DEPENDENCIES) (libgpgme_pthread_la_DEPENDENCIES): Remove $(assuan_libobjs). (libgpgme_la_LIBADD, libgpgme_pth_la_LIBADD) (libgpgme_glib_la_LIBADD, libgpgme_qt_la_LIBADD)) (libgpgme_pthread_la_LIBADD): Replace $(assuan_libobjs) by @LIBASSUAN_LIBS@. * priv-io.h [!HAVE_W32_SYSTEM]: Declare _gpgme_io_recvmsg, _gpgme_io_sendmsg, _gpgme_io_waitpid. * engine-backend.h: Define with [ENABLE_ASSUAN] instead of [ENABLE_GPGSM]. * posix-io.c (_gpgme_io_waitpid): Make non-static. * util.h (ENABLE_ASSUAN): Declar _gpgme_assuan_system_hooks, _gpgme_assuan_malloc_hooks, _gpgme_assuan_log_cb. * engine-gpgsm.c: Don't map assuan error codes. Use assuan_release instead of assuan_disconnect. (map_assuan_error): Remove function. (gpgsm_new): Use new assuan context interface. * engine-assuan.c: Use assuan_release instead of assuan_disconnect. (llass_new): Use new assuan context interface.
This commit is contained in:
parent
06e22ca339
commit
e782b1ab06
@ -1,3 +1,11 @@
|
|||||||
|
2009-10-20 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
|
* configure.ac: Replace internal libassuan by external libassuan.
|
||||||
|
* m4/libassuan.m4: New file.
|
||||||
|
* Makefile.am (assuan): Remove variable.
|
||||||
|
(SUBDIRS): Remove ${assuan}.
|
||||||
|
* assuan/: Removed.
|
||||||
|
|
||||||
2009-06-22 Marcus Brinkmann <marcus@g10code.de>
|
2009-06-22 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
* configure.ac: Add AC_TYPE_UINTPTR_T.
|
* configure.ac: Add AC_TYPE_UINTPTR_T.
|
||||||
|
@ -26,11 +26,6 @@ DISTCHECK_CONFIGURE_FLAGS = --with-gpg="@GPG@"
|
|||||||
|
|
||||||
EXTRA_DIST = gpgme.spec.in autogen.sh
|
EXTRA_DIST = gpgme.spec.in autogen.sh
|
||||||
|
|
||||||
if BUILD_ASSUAN
|
|
||||||
assuan = assuan
|
|
||||||
else
|
|
||||||
assuan =
|
|
||||||
endif
|
|
||||||
|
|
||||||
if BUILD_COMPLUS
|
if BUILD_COMPLUS
|
||||||
complus = complus
|
complus = complus
|
||||||
@ -44,7 +39,7 @@ else
|
|||||||
tests =
|
tests =
|
||||||
endif
|
endif
|
||||||
|
|
||||||
SUBDIRS = ${assuan} src ${tests} doc ${complus} lang
|
SUBDIRS = src ${tests} doc ${complus} lang
|
||||||
|
|
||||||
# Fix the version of the spec file and create a file named VERSION
|
# Fix the version of the spec file and create a file named VERSION
|
||||||
# to be used for patch's Prereq: feature.
|
# to be used for patch's Prereq: feature.
|
||||||
|
1339
assuan/ChangeLog
1339
assuan/ChangeLog
File diff suppressed because it is too large
Load Diff
@ -1,53 +0,0 @@
|
|||||||
# Assuan Makefile
|
|
||||||
# Copyright (C) 2001, 2002, 2003 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, write to the Free Software
|
|
||||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
||||||
|
|
||||||
## Process this file with automake to produce Makefile.in
|
|
||||||
|
|
||||||
EXTRA_DIST = mkerrors
|
|
||||||
INCLUDES = -I.. -I$(top_srcdir)/src
|
|
||||||
BUILT_SOURCES = assuan-errors.c
|
|
||||||
MOSTLYCLEANFILES = assuan-errors.c
|
|
||||||
|
|
||||||
noinst_LTLIBRARIES = libassuan.la
|
|
||||||
|
|
||||||
AM_CPPFLAGS = -D_ASSUAN_IN_GPGME_BUILD_ASSUAN
|
|
||||||
|
|
||||||
#libassuan_la_LDFLAGS =
|
|
||||||
libassuan_la_SOURCES = \
|
|
||||||
assuan.h \
|
|
||||||
assuan-defs.h \
|
|
||||||
assuan-util.c \
|
|
||||||
assuan-errors.c \
|
|
||||||
assuan-buffer.c \
|
|
||||||
assuan-handler.c \
|
|
||||||
assuan-inquire.c \
|
|
||||||
assuan-listen.c \
|
|
||||||
assuan-connect.c \
|
|
||||||
assuan-client.c \
|
|
||||||
assuan-pipe-server.c \
|
|
||||||
assuan-socket-server.c \
|
|
||||||
assuan-pipe-connect.c \
|
|
||||||
assuan-socket-connect.c \
|
|
||||||
assuan-uds.c \
|
|
||||||
assuan-io.c \
|
|
||||||
assuan-logging.c \
|
|
||||||
assuan-socket.c
|
|
||||||
|
|
||||||
assuan-errors.c : assuan.h mkerrors
|
|
||||||
$(srcdir)/mkerrors < $(srcdir)/assuan.h > assuan-errors.c
|
|
@ -1,45 +0,0 @@
|
|||||||
This is a modified copy of the libassuan library. Don't modify it,
|
|
||||||
but instead modify the original Assuan library and merge the changes
|
|
||||||
back into this copy.
|
|
||||||
|
|
||||||
The changes to the original libassuan, that have to preserved when
|
|
||||||
updating this directory, are:
|
|
||||||
|
|
||||||
* Makefile.am
|
|
||||||
** Build the library with libtool as a convenience library, which can
|
|
||||||
be linked into the shared library GPGME.
|
|
||||||
** Do not install the library or the header file.
|
|
||||||
** Define -D_ASSUAN_IN_GPGME_BUILD_ASSUAN to wrap some POSIX functions
|
|
||||||
with ATH replacements.
|
|
||||||
|
|
||||||
* assuan.h
|
|
||||||
** Preserve the block between "Begin/End GPGME specific modifications".
|
|
||||||
In particular make sure that
|
|
||||||
#define _ASSUAN_EXT_SYM_PREFIX _gpgme_
|
|
||||||
#define _ASSUAN_NO_PTH
|
|
||||||
#define _ASSUAN_NO_FIXED_SIGNALS
|
|
||||||
#define _ASSUAN_USE_DOUBLE_FORK
|
|
||||||
are defined. This puts all exported Assuan functions in the _gpgme
|
|
||||||
namespace. It also wraps all system functions that are wrapped by
|
|
||||||
GNU Pth to _gpgme wrappers.
|
|
||||||
|
|
||||||
* assuan-io-pth.c
|
|
||||||
We don't need this file as GPGME doesn't use sendmsg and recvmsg.
|
|
||||||
If it would, we would need to pick up the W32 implementation.
|
|
||||||
|
|
||||||
* assuan-io.c
|
|
||||||
** _assuan_simple_read() and _assuan_simple_write() must always use
|
|
||||||
read()/write() (which actually translates to _gpgme_io_read() and
|
|
||||||
_gpgme_io_write()). _assuan_close must always() use close() (which
|
|
||||||
translates to _gpgme_io_close()).
|
|
||||||
|
|
||||||
|
|
||||||
Copyright 2004, 2007 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.
|
|
@ -1,565 +0,0 @@
|
|||||||
/* assuan-buffer.c - read and send data
|
|
||||||
* Copyright (C) 2001, 2002, 2003, 2004, 2006 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#ifdef HAVE_W32_SYSTEM
|
|
||||||
#include <process.h>
|
|
||||||
#endif
|
|
||||||
#include "assuan-defs.h"
|
|
||||||
|
|
||||||
|
|
||||||
/* Extended version of write(2) to guarantee that all bytes are
|
|
||||||
written. Returns 0 on success or -1 and ERRNO on failure. */
|
|
||||||
static int
|
|
||||||
writen (assuan_context_t ctx, const char *buffer, size_t length)
|
|
||||||
{
|
|
||||||
while (length)
|
|
||||||
{
|
|
||||||
ssize_t nwritten = ctx->io->writefnc (ctx, buffer, length);
|
|
||||||
|
|
||||||
if (nwritten < 0)
|
|
||||||
{
|
|
||||||
if (errno == EINTR)
|
|
||||||
continue;
|
|
||||||
return -1; /* write error */
|
|
||||||
}
|
|
||||||
length -= nwritten;
|
|
||||||
buffer += nwritten;
|
|
||||||
}
|
|
||||||
return 0; /* okay */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read an entire line. Returns 0 on success or -1 and ERRNO on
|
|
||||||
failure. EOF is indictated by setting the integer at address
|
|
||||||
R_EOF. Note: BUF, R_NREAD and R_EOF contain a valid result even if
|
|
||||||
an error is returned. */
|
|
||||||
static int
|
|
||||||
readline (assuan_context_t ctx, char *buf, size_t buflen,
|
|
||||||
int *r_nread, int *r_eof)
|
|
||||||
{
|
|
||||||
size_t nleft = buflen;
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
*r_eof = 0;
|
|
||||||
*r_nread = 0;
|
|
||||||
while (nleft > 0)
|
|
||||||
{
|
|
||||||
ssize_t n = ctx->io->readfnc (ctx, buf, nleft);
|
|
||||||
|
|
||||||
if (n < 0)
|
|
||||||
{
|
|
||||||
if (errno == EINTR)
|
|
||||||
continue;
|
|
||||||
return -1; /* read error */
|
|
||||||
}
|
|
||||||
else if (!n)
|
|
||||||
{
|
|
||||||
*r_eof = 1;
|
|
||||||
break; /* allow incomplete lines */
|
|
||||||
}
|
|
||||||
p = buf;
|
|
||||||
nleft -= n;
|
|
||||||
buf += n;
|
|
||||||
*r_nread += n;
|
|
||||||
|
|
||||||
p = memrchr (p, '\n', n);
|
|
||||||
if (p)
|
|
||||||
break; /* at least one full line available - that's enough for now */
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Function returns an Assuan error. */
|
|
||||||
assuan_error_t
|
|
||||||
_assuan_read_line (assuan_context_t ctx)
|
|
||||||
{
|
|
||||||
char *line = ctx->inbound.line;
|
|
||||||
int nread, atticlen;
|
|
||||||
int rc;
|
|
||||||
char *endp = 0;
|
|
||||||
|
|
||||||
if (ctx->inbound.eof)
|
|
||||||
return _assuan_error (-1);
|
|
||||||
|
|
||||||
atticlen = ctx->inbound.attic.linelen;
|
|
||||||
if (atticlen)
|
|
||||||
{
|
|
||||||
memcpy (line, ctx->inbound.attic.line, atticlen);
|
|
||||||
ctx->inbound.attic.linelen = 0;
|
|
||||||
|
|
||||||
endp = memchr (line, '\n', atticlen);
|
|
||||||
if (endp)
|
|
||||||
/* Found another line in the attic. */
|
|
||||||
{
|
|
||||||
rc = 0;
|
|
||||||
nread = atticlen;
|
|
||||||
atticlen = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
/* There is pending data but not a full line. */
|
|
||||||
{
|
|
||||||
assert (atticlen < LINELENGTH);
|
|
||||||
rc = readline (ctx, line + atticlen,
|
|
||||||
LINELENGTH - atticlen, &nread, &ctx->inbound.eof);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
/* No pending data. */
|
|
||||||
rc = readline (ctx, line, LINELENGTH,
|
|
||||||
&nread, &ctx->inbound.eof);
|
|
||||||
if (rc)
|
|
||||||
{
|
|
||||||
int saved_errno = errno;
|
|
||||||
|
|
||||||
if (ctx->log_fp)
|
|
||||||
fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- [Error: %s]\n",
|
|
||||||
assuan_get_assuan_log_prefix (),
|
|
||||||
(unsigned int)getpid (), (int)ctx->inbound.fd,
|
|
||||||
strerror (errno));
|
|
||||||
|
|
||||||
if (saved_errno == EAGAIN)
|
|
||||||
{
|
|
||||||
/* We have to save a partial line. */
|
|
||||||
memcpy (ctx->inbound.attic.line, line, atticlen + nread);
|
|
||||||
ctx->inbound.attic.pending = 0;
|
|
||||||
ctx->inbound.attic.linelen = atticlen + nread;
|
|
||||||
}
|
|
||||||
|
|
||||||
errno = saved_errno;
|
|
||||||
return _assuan_error (ASSUAN_Read_Error);
|
|
||||||
}
|
|
||||||
if (!nread)
|
|
||||||
{
|
|
||||||
assert (ctx->inbound.eof);
|
|
||||||
if (ctx->log_fp)
|
|
||||||
fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- [EOF]\n",
|
|
||||||
assuan_get_assuan_log_prefix (),
|
|
||||||
(unsigned int)getpid (), (int)ctx->inbound.fd);
|
|
||||||
return _assuan_error (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->inbound.attic.pending = 0;
|
|
||||||
nread += atticlen;
|
|
||||||
|
|
||||||
if (! endp)
|
|
||||||
endp = memchr (line, '\n', nread);
|
|
||||||
|
|
||||||
if (endp)
|
|
||||||
{
|
|
||||||
unsigned monitor_result;
|
|
||||||
int n = endp - line + 1;
|
|
||||||
|
|
||||||
if (n < nread)
|
|
||||||
/* LINE contains more than one line. We copy it to the attic
|
|
||||||
now as handlers are allowed to modify the passed
|
|
||||||
buffer. */
|
|
||||||
{
|
|
||||||
int len = nread - n;
|
|
||||||
memcpy (ctx->inbound.attic.line, endp + 1, len);
|
|
||||||
ctx->inbound.attic.pending = memrchr (endp + 1, '\n', len) ? 1 : 0;
|
|
||||||
ctx->inbound.attic.linelen = len;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (endp != line && endp[-1] == '\r')
|
|
||||||
endp --;
|
|
||||||
*endp = 0;
|
|
||||||
|
|
||||||
ctx->inbound.linelen = endp - line;
|
|
||||||
|
|
||||||
monitor_result = (ctx->io_monitor
|
|
||||||
? ctx->io_monitor (ctx, 0,
|
|
||||||
ctx->inbound.line,
|
|
||||||
ctx->inbound.linelen)
|
|
||||||
: 0);
|
|
||||||
if ( (monitor_result & 2) )
|
|
||||||
ctx->inbound.linelen = 0;
|
|
||||||
|
|
||||||
if (ctx->log_fp && !(monitor_result & 1))
|
|
||||||
{
|
|
||||||
fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- ",
|
|
||||||
assuan_get_assuan_log_prefix (),
|
|
||||||
(unsigned int)getpid (), (int)ctx->inbound.fd);
|
|
||||||
if (ctx->confidential)
|
|
||||||
fputs ("[Confidential data not shown]", ctx->log_fp);
|
|
||||||
else
|
|
||||||
_assuan_log_print_buffer (ctx->log_fp,
|
|
||||||
ctx->inbound.line,
|
|
||||||
ctx->inbound.linelen);
|
|
||||||
putc ('\n', ctx->log_fp);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (ctx->log_fp)
|
|
||||||
fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- [Invalid line]\n",
|
|
||||||
assuan_get_assuan_log_prefix (),
|
|
||||||
(unsigned int)getpid (), (int)ctx->inbound.fd);
|
|
||||||
*line = 0;
|
|
||||||
ctx->inbound.linelen = 0;
|
|
||||||
return _assuan_error (ctx->inbound.eof
|
|
||||||
? ASSUAN_Line_Not_Terminated
|
|
||||||
: ASSUAN_Line_Too_Long);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Read the next line from the client or server and return a pointer
|
|
||||||
in *LINE to a buffer holding the line. LINELEN is the length of
|
|
||||||
*LINE. The buffer is valid until the next read operation on it.
|
|
||||||
The caller may modify the buffer. The buffer is invalid (i.e. must
|
|
||||||
not be used) if an error is returned.
|
|
||||||
|
|
||||||
Returns 0 on success or an assuan error code.
|
|
||||||
See also: assuan_pending_line().
|
|
||||||
*/
|
|
||||||
assuan_error_t
|
|
||||||
assuan_read_line (assuan_context_t ctx, char **line, size_t *linelen)
|
|
||||||
{
|
|
||||||
assuan_error_t err;
|
|
||||||
|
|
||||||
if (!ctx)
|
|
||||||
return _assuan_error (ASSUAN_Invalid_Value);
|
|
||||||
|
|
||||||
err = _assuan_read_line (ctx);
|
|
||||||
|
|
||||||
*line = ctx->inbound.line;
|
|
||||||
*linelen = ctx->inbound.linelen;
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Return true if a full line is buffered (i.e. an entire line may be
|
|
||||||
read without any I/O). */
|
|
||||||
int
|
|
||||||
assuan_pending_line (assuan_context_t ctx)
|
|
||||||
{
|
|
||||||
return ctx && ctx->inbound.attic.pending;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
assuan_error_t
|
|
||||||
_assuan_write_line (assuan_context_t ctx, const char *prefix,
|
|
||||||
const char *line, size_t len)
|
|
||||||
{
|
|
||||||
assuan_error_t rc = 0;
|
|
||||||
size_t prefixlen = prefix? strlen (prefix):0;
|
|
||||||
unsigned int monitor_result;
|
|
||||||
|
|
||||||
/* Make sure that the line is short enough. */
|
|
||||||
if (len + prefixlen + 2 > ASSUAN_LINELENGTH)
|
|
||||||
{
|
|
||||||
if (ctx->log_fp)
|
|
||||||
fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> "
|
|
||||||
"[supplied line too long -truncated]\n",
|
|
||||||
assuan_get_assuan_log_prefix (),
|
|
||||||
(unsigned int)getpid (), (int)ctx->inbound.fd);
|
|
||||||
if (prefixlen > 5)
|
|
||||||
prefixlen = 5;
|
|
||||||
if (len > ASSUAN_LINELENGTH - prefixlen - 2)
|
|
||||||
len = ASSUAN_LINELENGTH - prefixlen - 2 - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
monitor_result = (ctx->io_monitor
|
|
||||||
? ctx->io_monitor (ctx, 1, line, len)
|
|
||||||
: 0);
|
|
||||||
|
|
||||||
/* Fixme: we should do some kind of line buffering. */
|
|
||||||
if (ctx->log_fp && !(monitor_result & 1))
|
|
||||||
{
|
|
||||||
fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> ",
|
|
||||||
assuan_get_assuan_log_prefix (),
|
|
||||||
(unsigned int)getpid (), (int)ctx->inbound.fd);
|
|
||||||
if (ctx->confidential)
|
|
||||||
fputs ("[Confidential data not shown]", ctx->log_fp);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (prefixlen)
|
|
||||||
_assuan_log_print_buffer (ctx->log_fp, prefix, prefixlen);
|
|
||||||
_assuan_log_print_buffer (ctx->log_fp, line, len);
|
|
||||||
}
|
|
||||||
putc ('\n', ctx->log_fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prefixlen && !(monitor_result & 2))
|
|
||||||
{
|
|
||||||
rc = writen (ctx, prefix, prefixlen);
|
|
||||||
if (rc)
|
|
||||||
rc = _assuan_error (ASSUAN_Write_Error);
|
|
||||||
}
|
|
||||||
if (!rc && !(monitor_result & 2))
|
|
||||||
{
|
|
||||||
rc = writen (ctx, line, len);
|
|
||||||
if (rc)
|
|
||||||
rc = _assuan_error (ASSUAN_Write_Error);
|
|
||||||
if (!rc)
|
|
||||||
{
|
|
||||||
rc = writen (ctx, "\n", 1);
|
|
||||||
if (rc)
|
|
||||||
rc = _assuan_error (ASSUAN_Write_Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
assuan_error_t
|
|
||||||
assuan_write_line (assuan_context_t ctx, const char *line)
|
|
||||||
{
|
|
||||||
size_t len;
|
|
||||||
const char *s;
|
|
||||||
|
|
||||||
if (!ctx)
|
|
||||||
return _assuan_error (ASSUAN_Invalid_Value);
|
|
||||||
|
|
||||||
/* Make sure that we never take a LF from the user - this might
|
|
||||||
violate the protocol. */
|
|
||||||
s = strchr (line, '\n');
|
|
||||||
len = s? (s-line) : strlen (line);
|
|
||||||
|
|
||||||
if (ctx->log_fp && s)
|
|
||||||
fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> "
|
|
||||||
"[supplied line contained a LF - truncated]\n",
|
|
||||||
assuan_get_assuan_log_prefix (),
|
|
||||||
(unsigned int)getpid (), (int)ctx->inbound.fd);
|
|
||||||
|
|
||||||
return _assuan_write_line (ctx, NULL, line, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Write out the data in buffer as datalines with line wrapping and
|
|
||||||
percent escaping. This function is used for GNU's custom streams. */
|
|
||||||
int
|
|
||||||
_assuan_cookie_write_data (void *cookie, const char *buffer, size_t orig_size)
|
|
||||||
{
|
|
||||||
assuan_context_t ctx = cookie;
|
|
||||||
size_t size = orig_size;
|
|
||||||
char *line;
|
|
||||||
size_t linelen;
|
|
||||||
|
|
||||||
if (ctx->outbound.data.error)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
line = ctx->outbound.data.line;
|
|
||||||
linelen = ctx->outbound.data.linelen;
|
|
||||||
line += linelen;
|
|
||||||
while (size)
|
|
||||||
{
|
|
||||||
unsigned int monitor_result;
|
|
||||||
|
|
||||||
/* Insert data line header. */
|
|
||||||
if (!linelen)
|
|
||||||
{
|
|
||||||
*line++ = 'D';
|
|
||||||
*line++ = ' ';
|
|
||||||
linelen += 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Copy data, keep space for the CRLF and to escape one character. */
|
|
||||||
while (size && linelen < LINELENGTH-2-2)
|
|
||||||
{
|
|
||||||
if (*buffer == '%' || *buffer == '\r' || *buffer == '\n')
|
|
||||||
{
|
|
||||||
sprintf (line, "%%%02X", *(unsigned char*)buffer);
|
|
||||||
line += 3;
|
|
||||||
linelen += 3;
|
|
||||||
buffer++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*line++ = *buffer++;
|
|
||||||
linelen++;
|
|
||||||
}
|
|
||||||
size--;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
monitor_result = (ctx->io_monitor
|
|
||||||
? ctx->io_monitor (ctx, 1,
|
|
||||||
ctx->outbound.data.line, linelen)
|
|
||||||
: 0);
|
|
||||||
|
|
||||||
if (linelen >= LINELENGTH-2-2)
|
|
||||||
{
|
|
||||||
if (ctx->log_fp && !(monitor_result & 1))
|
|
||||||
{
|
|
||||||
fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> ",
|
|
||||||
assuan_get_assuan_log_prefix (),
|
|
||||||
(unsigned int)getpid (), (int)ctx->inbound.fd);
|
|
||||||
|
|
||||||
if (ctx->confidential)
|
|
||||||
fputs ("[Confidential data not shown]", ctx->log_fp);
|
|
||||||
else
|
|
||||||
_assuan_log_print_buffer (ctx->log_fp,
|
|
||||||
ctx->outbound.data.line,
|
|
||||||
linelen);
|
|
||||||
putc ('\n', ctx->log_fp);
|
|
||||||
}
|
|
||||||
*line++ = '\n';
|
|
||||||
linelen++;
|
|
||||||
if ( !(monitor_result & 2)
|
|
||||||
&& writen (ctx, ctx->outbound.data.line, linelen))
|
|
||||||
{
|
|
||||||
ctx->outbound.data.error = _assuan_error (ASSUAN_Write_Error);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
line = ctx->outbound.data.line;
|
|
||||||
linelen = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->outbound.data.linelen = linelen;
|
|
||||||
return (int)orig_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Write out any buffered data
|
|
||||||
This function is used for GNU's custom streams */
|
|
||||||
int
|
|
||||||
_assuan_cookie_write_flush (void *cookie)
|
|
||||||
{
|
|
||||||
assuan_context_t ctx = cookie;
|
|
||||||
char *line;
|
|
||||||
size_t linelen;
|
|
||||||
unsigned int monitor_result;
|
|
||||||
|
|
||||||
if (ctx->outbound.data.error)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
line = ctx->outbound.data.line;
|
|
||||||
linelen = ctx->outbound.data.linelen;
|
|
||||||
line += linelen;
|
|
||||||
|
|
||||||
monitor_result = (ctx->io_monitor
|
|
||||||
? ctx->io_monitor (ctx, 1,
|
|
||||||
ctx->outbound.data.line, linelen)
|
|
||||||
: 0);
|
|
||||||
|
|
||||||
if (linelen)
|
|
||||||
{
|
|
||||||
if (ctx->log_fp && !(monitor_result & 1))
|
|
||||||
{
|
|
||||||
fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> ",
|
|
||||||
assuan_get_assuan_log_prefix (),
|
|
||||||
(unsigned int)getpid (), (int)ctx->inbound.fd);
|
|
||||||
if (ctx->confidential)
|
|
||||||
fputs ("[Confidential data not shown]", ctx->log_fp);
|
|
||||||
else
|
|
||||||
_assuan_log_print_buffer (ctx->log_fp,
|
|
||||||
ctx->outbound.data.line, linelen);
|
|
||||||
putc ('\n', ctx->log_fp);
|
|
||||||
}
|
|
||||||
*line++ = '\n';
|
|
||||||
linelen++;
|
|
||||||
if ( !(monitor_result & 2)
|
|
||||||
&& writen (ctx, ctx->outbound.data.line, linelen))
|
|
||||||
{
|
|
||||||
ctx->outbound.data.error = _assuan_error (ASSUAN_Write_Error);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
ctx->outbound.data.linelen = 0;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* assuan_send_data:
|
|
||||||
* @ctx: An assuan context
|
|
||||||
* @buffer: Data to send or NULL to flush
|
|
||||||
* @length: length of the data to send/
|
|
||||||
*
|
|
||||||
* This function may be used by the server or the client to send data
|
|
||||||
* lines. The data will be escaped as required by the Assuan protocol
|
|
||||||
* and may get buffered until a line is full. To force sending the
|
|
||||||
* data out @buffer may be passed as NULL (in which case @length must
|
|
||||||
* also be 0); however when used by a client this flush operation does
|
|
||||||
* also send the terminating "END" command to terminate the reponse on
|
|
||||||
* a INQUIRE response. However, when assuan_transact() is used, this
|
|
||||||
* function takes care of sending END itself.
|
|
||||||
*
|
|
||||||
* If BUFFER is NULL and LENGTH is 1 and we are a client, a "CAN" is
|
|
||||||
* send instead of an "END".
|
|
||||||
*
|
|
||||||
* Return value: 0 on success or an error code
|
|
||||||
**/
|
|
||||||
|
|
||||||
assuan_error_t
|
|
||||||
assuan_send_data (assuan_context_t ctx, const void *buffer, size_t length)
|
|
||||||
{
|
|
||||||
if (!ctx)
|
|
||||||
return _assuan_error (ASSUAN_Invalid_Value);
|
|
||||||
if (!buffer && length > 1)
|
|
||||||
return _assuan_error (ASSUAN_Invalid_Value);
|
|
||||||
|
|
||||||
if (!buffer)
|
|
||||||
{ /* flush what we have */
|
|
||||||
_assuan_cookie_write_flush (ctx);
|
|
||||||
if (ctx->outbound.data.error)
|
|
||||||
return ctx->outbound.data.error;
|
|
||||||
if (!ctx->is_server)
|
|
||||||
return assuan_write_line (ctx, length == 1? "CAN":"END");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_assuan_cookie_write_data (ctx, buffer, length);
|
|
||||||
if (ctx->outbound.data.error)
|
|
||||||
return ctx->outbound.data.error;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
assuan_error_t
|
|
||||||
assuan_sendfd (assuan_context_t ctx, assuan_fd_t fd)
|
|
||||||
{
|
|
||||||
/* It is explicitly allowed to use (NULL, -1) as a runtime test to
|
|
||||||
check whether descriptor passing is available. */
|
|
||||||
if (!ctx && fd == ASSUAN_INVALID_FD)
|
|
||||||
#ifdef USE_DESCRIPTOR_PASSING
|
|
||||||
return 0;
|
|
||||||
#else
|
|
||||||
return _assuan_error (ASSUAN_Not_Implemented);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (! ctx->io->sendfd)
|
|
||||||
return set_error (ctx, Not_Implemented,
|
|
||||||
"server does not support sending and receiving "
|
|
||||||
"of file descriptors");
|
|
||||||
return ctx->io->sendfd (ctx, fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
assuan_error_t
|
|
||||||
assuan_receivefd (assuan_context_t ctx, assuan_fd_t *fd)
|
|
||||||
{
|
|
||||||
if (! ctx->io->receivefd)
|
|
||||||
return set_error (ctx, Not_Implemented,
|
|
||||||
"server does not support sending and receiving "
|
|
||||||
"of file descriptors");
|
|
||||||
return ctx->io->receivefd (ctx, fd);
|
|
||||||
}
|
|
@ -1,232 +0,0 @@
|
|||||||
/* assuan-client.c - client functions
|
|
||||||
* Copyright (C) 2001, 2002, 2005 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "assuan-defs.h"
|
|
||||||
|
|
||||||
#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
|
|
||||||
*(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
|
|
||||||
#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
|
|
||||||
|
|
||||||
|
|
||||||
assuan_error_t
|
|
||||||
_assuan_read_from_server (assuan_context_t ctx, int *okay, int *off)
|
|
||||||
{
|
|
||||||
char *line;
|
|
||||||
int linelen;
|
|
||||||
assuan_error_t rc;
|
|
||||||
|
|
||||||
*okay = 0;
|
|
||||||
*off = 0;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
rc = _assuan_read_line (ctx);
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
line = ctx->inbound.line;
|
|
||||||
linelen = ctx->inbound.linelen;
|
|
||||||
}
|
|
||||||
while (*line == '#' || !linelen);
|
|
||||||
|
|
||||||
if (linelen >= 1
|
|
||||||
&& line[0] == 'D' && line[1] == ' ')
|
|
||||||
{
|
|
||||||
*okay = 2; /* data line */
|
|
||||||
*off = 2;
|
|
||||||
}
|
|
||||||
else if (linelen >= 1
|
|
||||||
&& line[0] == 'S'
|
|
||||||
&& (line[1] == '\0' || line[1] == ' '))
|
|
||||||
{
|
|
||||||
*okay = 4;
|
|
||||||
*off = 1;
|
|
||||||
while (line[*off] == ' ')
|
|
||||||
++*off;
|
|
||||||
}
|
|
||||||
else if (linelen >= 2
|
|
||||||
&& line[0] == 'O' && line[1] == 'K'
|
|
||||||
&& (line[2] == '\0' || line[2] == ' '))
|
|
||||||
{
|
|
||||||
*okay = 1;
|
|
||||||
*off = 2;
|
|
||||||
while (line[*off] == ' ')
|
|
||||||
++*off;
|
|
||||||
}
|
|
||||||
else if (linelen >= 3
|
|
||||||
&& line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
|
|
||||||
&& (line[3] == '\0' || line[3] == ' '))
|
|
||||||
{
|
|
||||||
*okay = 0;
|
|
||||||
*off = 3;
|
|
||||||
while (line[*off] == ' ')
|
|
||||||
++*off;
|
|
||||||
}
|
|
||||||
else if (linelen >= 7
|
|
||||||
&& line[0] == 'I' && line[1] == 'N' && line[2] == 'Q'
|
|
||||||
&& line[3] == 'U' && line[4] == 'I' && line[5] == 'R'
|
|
||||||
&& line[6] == 'E'
|
|
||||||
&& (line[7] == '\0' || line[7] == ' '))
|
|
||||||
{
|
|
||||||
*okay = 3;
|
|
||||||
*off = 7;
|
|
||||||
while (line[*off] == ' ')
|
|
||||||
++*off;
|
|
||||||
}
|
|
||||||
else if (linelen >= 3
|
|
||||||
&& line[0] == 'E' && line[1] == 'N' && line[2] == 'D'
|
|
||||||
&& (line[3] == '\0' || line[3] == ' '))
|
|
||||||
{
|
|
||||||
*okay = 5; /* end line */
|
|
||||||
*off = 3;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
rc = _assuan_error (ASSUAN_Invalid_Response);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* assuan_transact:
|
|
||||||
* @ctx: The Assuan context
|
|
||||||
* @command: Command line to be send to the server
|
|
||||||
* @data_cb: Callback function for data lines
|
|
||||||
* @data_cb_arg: first argument passed to @data_cb
|
|
||||||
* @inquire_cb: Callback function for a inquire response
|
|
||||||
* @inquire_cb_arg: first argument passed to @inquire_cb
|
|
||||||
* @status_cb: Callback function for a status response
|
|
||||||
* @status_cb_arg: first argument passed to @status_cb
|
|
||||||
*
|
|
||||||
* FIXME: Write documentation
|
|
||||||
*
|
|
||||||
* Return value: 0 on success or error code. The error code may be
|
|
||||||
* the one one returned by the server in error lines or from the
|
|
||||||
* callback functions. Take care: When a callback returns an error
|
|
||||||
* this function returns immediately with an error and thus the caller
|
|
||||||
* will altter return an Assuan error (write erro in most cases).
|
|
||||||
**/
|
|
||||||
assuan_error_t
|
|
||||||
assuan_transact (assuan_context_t ctx,
|
|
||||||
const char *command,
|
|
||||||
int (*data_cb)(void *, const void *, size_t),
|
|
||||||
void *data_cb_arg,
|
|
||||||
int (*inquire_cb)(void*, const char *),
|
|
||||||
void *inquire_cb_arg,
|
|
||||||
int (*status_cb)(void*, const char *),
|
|
||||||
void *status_cb_arg)
|
|
||||||
{
|
|
||||||
assuan_error_t rc;
|
|
||||||
int okay, off;
|
|
||||||
char *line;
|
|
||||||
int linelen;
|
|
||||||
|
|
||||||
rc = assuan_write_line (ctx, command);
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
if (*command == '#' || !*command)
|
|
||||||
return 0; /* Don't expect a response for a comment line. */
|
|
||||||
|
|
||||||
again:
|
|
||||||
rc = _assuan_read_from_server (ctx, &okay, &off);
|
|
||||||
if (rc)
|
|
||||||
return rc; /* error reading from server */
|
|
||||||
|
|
||||||
line = ctx->inbound.line + off;
|
|
||||||
linelen = ctx->inbound.linelen - off;
|
|
||||||
|
|
||||||
if (!okay)
|
|
||||||
{
|
|
||||||
rc = atoi (line);
|
|
||||||
if (rc > 0 && rc < 100)
|
|
||||||
rc = _assuan_error (ASSUAN_Server_Fault);
|
|
||||||
else if (rc > 0 && rc <= 405)
|
|
||||||
rc = _assuan_error (rc);
|
|
||||||
}
|
|
||||||
else if (okay == 2)
|
|
||||||
{
|
|
||||||
if (!data_cb)
|
|
||||||
rc = _assuan_error (ASSUAN_No_Data_Callback);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char *s, *d;
|
|
||||||
|
|
||||||
for (s=d=line; linelen; linelen--)
|
|
||||||
{
|
|
||||||
if (*s == '%' && linelen > 2)
|
|
||||||
{ /* handle escaping */
|
|
||||||
s++;
|
|
||||||
*d++ = xtoi_2 (s);
|
|
||||||
s += 2;
|
|
||||||
linelen -= 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
*d++ = *s++;
|
|
||||||
}
|
|
||||||
*d = 0; /* add a hidden string terminator */
|
|
||||||
rc = data_cb (data_cb_arg, line, d - line);
|
|
||||||
if (!rc)
|
|
||||||
goto again;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (okay == 3)
|
|
||||||
{
|
|
||||||
if (!inquire_cb)
|
|
||||||
{
|
|
||||||
assuan_write_line (ctx, "END"); /* get out of inquire mode */
|
|
||||||
_assuan_read_from_server (ctx, &okay, &off); /* dummy read */
|
|
||||||
rc = _assuan_error (ASSUAN_No_Inquire_Callback);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rc = inquire_cb (inquire_cb_arg, line);
|
|
||||||
if (!rc)
|
|
||||||
rc = assuan_send_data (ctx, NULL, 0); /* flush and send END */
|
|
||||||
if (!rc)
|
|
||||||
goto again;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (okay == 4)
|
|
||||||
{
|
|
||||||
if (status_cb)
|
|
||||||
rc = status_cb (status_cb_arg, line);
|
|
||||||
if (!rc)
|
|
||||||
goto again;
|
|
||||||
}
|
|
||||||
else if (okay == 5)
|
|
||||||
{
|
|
||||||
if (!data_cb)
|
|
||||||
rc = _assuan_error (ASSUAN_No_Data_Callback);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rc = data_cb (data_cb_arg, NULL, 0);
|
|
||||||
if (!rc)
|
|
||||||
goto again;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
@ -1,83 +0,0 @@
|
|||||||
/* assuan-connect.c - Establish a connection (client)
|
|
||||||
* Copyright (C) 2001, 2002 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include <config.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#ifndef HAVE_W32_SYSTEM
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "assuan-defs.h"
|
|
||||||
|
|
||||||
/* Disconnect and release the context CTX. */
|
|
||||||
void
|
|
||||||
assuan_disconnect (assuan_context_t ctx)
|
|
||||||
{
|
|
||||||
if (ctx)
|
|
||||||
{
|
|
||||||
assuan_write_line (ctx, "BYE");
|
|
||||||
ctx->finish_handler (ctx);
|
|
||||||
ctx->deinit_handler (ctx);
|
|
||||||
ctx->deinit_handler = NULL;
|
|
||||||
_assuan_release_context (ctx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return the PID of the peer or -1 if not known. This function works
|
|
||||||
in some situations where assuan_get_ucred fails. */
|
|
||||||
pid_t
|
|
||||||
assuan_get_pid (assuan_context_t ctx)
|
|
||||||
{
|
|
||||||
return (ctx && ctx->pid)? ctx->pid : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef HAVE_W32_SYSTEM
|
|
||||||
/* Return user credentials. PID, UID and GID may be given as NULL if
|
|
||||||
you are not interested in a value. For getting the pid of the
|
|
||||||
peer the assuan_get_pid is usually better suited. */
|
|
||||||
assuan_error_t
|
|
||||||
assuan_get_peercred (assuan_context_t ctx, pid_t *pid, uid_t *uid, gid_t *gid)
|
|
||||||
{
|
|
||||||
if (!ctx)
|
|
||||||
return _assuan_error (ASSUAN_Invalid_Value);
|
|
||||||
if (!ctx->peercred.valid)
|
|
||||||
return _assuan_error (ASSUAN_General_Error);
|
|
||||||
|
|
||||||
#ifdef HAVE_SO_PEERCRED
|
|
||||||
if (pid)
|
|
||||||
*pid = ctx->peercred.pid;
|
|
||||||
if (uid)
|
|
||||||
*uid = ctx->peercred.uid;
|
|
||||||
if (gid)
|
|
||||||
*gid = ctx->peercred.gid;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif /* HAVE_W32_SYSTEM */
|
|
@ -1,361 +0,0 @@
|
|||||||
/* assuan-defs.c - Internal definitions to Assuan
|
|
||||||
* Copyright (C) 2001, 2002, 2004, 2005, 2007, 2008 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, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
|
||||||
* USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef ASSUAN_DEFS_H
|
|
||||||
#define ASSUAN_DEFS_H
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#ifndef HAVE_W32_SYSTEM
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/un.h>
|
|
||||||
#else
|
|
||||||
#include <windows.h>
|
|
||||||
#endif
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "assuan.h"
|
|
||||||
|
|
||||||
#ifndef HAVE_W32_SYSTEM
|
|
||||||
#define DIRSEP_C '/'
|
|
||||||
#else
|
|
||||||
#define DIRSEP_C '\\'
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_W32_SYSTEM
|
|
||||||
/* Not needed anymore because the current mingw32 defines this in
|
|
||||||
sys/types.h */
|
|
||||||
/* typedef int ssize_t; */
|
|
||||||
|
|
||||||
/* Missing W32 functions */
|
|
||||||
int putc_unlocked (int c, FILE *stream);
|
|
||||||
void * memrchr (const void *block, int c, size_t size);
|
|
||||||
char * stpcpy (char *dest, const char *src);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define LINELENGTH ASSUAN_LINELENGTH
|
|
||||||
|
|
||||||
|
|
||||||
struct cmdtbl_s
|
|
||||||
{
|
|
||||||
const char *name;
|
|
||||||
int (*handler)(assuan_context_t, char *line);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* A structure to dispatch I/O functions. All these functions need to
|
|
||||||
return 0 on success and set ERRNO on failure. */
|
|
||||||
struct assuan_io
|
|
||||||
{
|
|
||||||
/* Routine to read from input_fd. */
|
|
||||||
ssize_t (*readfnc) (assuan_context_t, void *, size_t);
|
|
||||||
/* Routine to write to output_fd. */
|
|
||||||
ssize_t (*writefnc) (assuan_context_t, const void *, size_t);
|
|
||||||
/* Send a file descriptor. */
|
|
||||||
assuan_error_t (*sendfd) (assuan_context_t, assuan_fd_t);
|
|
||||||
/* Receive a file descriptor. */
|
|
||||||
assuan_error_t (*receivefd) (assuan_context_t, assuan_fd_t *);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* The global variable with the optional hook fucntions. */
|
|
||||||
extern struct assuan_io_hooks _assuan_io_hooks;
|
|
||||||
|
|
||||||
|
|
||||||
/* The context we use with most functions. */
|
|
||||||
struct assuan_context_s
|
|
||||||
{
|
|
||||||
assuan_error_t err_no;
|
|
||||||
const char *err_str;
|
|
||||||
int os_errno; /* Last system error number used with certain
|
|
||||||
error codes. */
|
|
||||||
|
|
||||||
/* Context specific flags (cf. assuan_flag_t). */
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
unsigned int no_waitpid:1; /* See ASSUAN_NO_WAITPID. */
|
|
||||||
} flags;
|
|
||||||
|
|
||||||
int confidential;
|
|
||||||
int is_server; /* Set if this is context belongs to a server */
|
|
||||||
int in_inquire;
|
|
||||||
int in_process_next;
|
|
||||||
int in_command;
|
|
||||||
|
|
||||||
/* The following members are used by assuan_inquire_ext. */
|
|
||||||
int (*inquire_cb) (void *cb_data, int rc, unsigned char *buf, size_t len);
|
|
||||||
void *inquire_cb_data;
|
|
||||||
void *inquire_membuf;
|
|
||||||
|
|
||||||
char *hello_line;
|
|
||||||
char *okay_line; /* See assuan_set_okay_line() */
|
|
||||||
|
|
||||||
void *user_pointer; /* For assuan_get_pointer and assuan_set_pointer (). */
|
|
||||||
|
|
||||||
FILE *log_fp;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
assuan_fd_t fd;
|
|
||||||
int eof;
|
|
||||||
char line[LINELENGTH];
|
|
||||||
int linelen; /* w/o CR, LF - might not be the same as
|
|
||||||
strlen(line) due to embedded nuls. However a nul
|
|
||||||
is always written at this pos. */
|
|
||||||
struct {
|
|
||||||
char line[LINELENGTH];
|
|
||||||
int linelen ;
|
|
||||||
int pending; /* i.e. at least one line is available in the attic */
|
|
||||||
} attic;
|
|
||||||
} inbound;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
assuan_fd_t fd;
|
|
||||||
struct {
|
|
||||||
FILE *fp;
|
|
||||||
char line[LINELENGTH];
|
|
||||||
int linelen;
|
|
||||||
int error;
|
|
||||||
} data;
|
|
||||||
} outbound;
|
|
||||||
|
|
||||||
int pipe_mode; /* We are in pipe mode, i.e. we can handle just one
|
|
||||||
connection and must terminate then. */
|
|
||||||
pid_t pid; /* The pid of the peer. */
|
|
||||||
assuan_fd_t listen_fd; /* The fd we are listening on (used by
|
|
||||||
socket servers) */
|
|
||||||
assuan_sock_nonce_t listen_nonce; /* Used with LISTEN_FD. */
|
|
||||||
assuan_fd_t connected_fd; /* helper */
|
|
||||||
|
|
||||||
struct {
|
|
||||||
int valid; /* Whether this structure has valid information. */
|
|
||||||
#ifdef HAVE_SO_PEERCRED
|
|
||||||
pid_t pid; /* The pid of the peer. */
|
|
||||||
uid_t uid; /* The uid of the peer. */
|
|
||||||
gid_t gid; /* The gid of the peer. */
|
|
||||||
#endif /* HAVE_SO_PEERCRED */
|
|
||||||
} peercred;
|
|
||||||
|
|
||||||
/* Used for Unix domain sockets. */
|
|
||||||
struct sockaddr_un myaddr;
|
|
||||||
struct sockaddr_un serveraddr;
|
|
||||||
|
|
||||||
/* Structure used for unix domain socket buffering. FIXME: We don't
|
|
||||||
use datagrams anymore thus we could get away with a simpler
|
|
||||||
buffering approach. */
|
|
||||||
struct {
|
|
||||||
void *buffer; /* Malloced buffer. */
|
|
||||||
int bufferallocated; /* Memory allocated. */
|
|
||||||
int bufferoffset; /* Offset of start of buffer. */
|
|
||||||
int buffersize; /* Bytes buffered. */
|
|
||||||
|
|
||||||
assuan_fd_t pendingfds[5]; /* Array to save received descriptors. */
|
|
||||||
int pendingfdscount; /* Number of received descriptors. */
|
|
||||||
} uds;
|
|
||||||
|
|
||||||
void (*deinit_handler)(assuan_context_t);
|
|
||||||
int (*accept_handler)(assuan_context_t);
|
|
||||||
int (*finish_handler)(assuan_context_t);
|
|
||||||
|
|
||||||
struct cmdtbl_s *cmdtbl;
|
|
||||||
size_t cmdtbl_used; /* used entries */
|
|
||||||
size_t cmdtbl_size; /* allocated size of table */
|
|
||||||
|
|
||||||
void (*bye_notify_fnc)(assuan_context_t);
|
|
||||||
void (*reset_notify_fnc)(assuan_context_t);
|
|
||||||
void (*cancel_notify_fnc)(assuan_context_t);
|
|
||||||
int (*option_handler_fnc)(assuan_context_t,const char*, const char*);
|
|
||||||
void (*input_notify_fnc)(assuan_context_t, const char *);
|
|
||||||
void (*output_notify_fnc)(assuan_context_t, const char *);
|
|
||||||
|
|
||||||
/* This function is called right after a command has been processed.
|
|
||||||
It may be used to command related cleanup. */
|
|
||||||
void (*post_cmd_notify_fnc)(assuan_context_t, int);
|
|
||||||
|
|
||||||
/* If set, this is called right before logging an I/O line. With
|
|
||||||
DIRECTION set to 1 it is called for an output oeration; 0 means
|
|
||||||
an input operation. If bit 0 is set in the return value, the
|
|
||||||
logging of the line will be suppressed. With bit 1 set, the
|
|
||||||
entire line will be ignored. */
|
|
||||||
unsigned int (*io_monitor)(assuan_context_t ctx,
|
|
||||||
int direction,
|
|
||||||
const char *line,
|
|
||||||
size_t linelen);
|
|
||||||
|
|
||||||
assuan_fd_t input_fd; /* Set by the INPUT command. */
|
|
||||||
assuan_fd_t output_fd; /* Set by the OUTPUT command. */
|
|
||||||
|
|
||||||
/* io routines. */
|
|
||||||
struct assuan_io *io;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*-- assuan-pipe-server.c --*/
|
|
||||||
int _assuan_new_context (assuan_context_t *r_ctx);
|
|
||||||
void _assuan_release_context (assuan_context_t ctx);
|
|
||||||
|
|
||||||
/*-- assuan-uds.c --*/
|
|
||||||
void _assuan_uds_close_fds (assuan_context_t ctx);
|
|
||||||
void _assuan_uds_deinit (assuan_context_t ctx);
|
|
||||||
void _assuan_init_uds_io (assuan_context_t ctx);
|
|
||||||
|
|
||||||
|
|
||||||
/*-- assuan-handler.c --*/
|
|
||||||
int _assuan_register_std_commands (assuan_context_t ctx);
|
|
||||||
|
|
||||||
/*-- assuan-buffer.c --*/
|
|
||||||
assuan_error_t _assuan_read_line (assuan_context_t ctx);
|
|
||||||
int _assuan_cookie_write_data (void *cookie, const char *buffer, size_t size);
|
|
||||||
int _assuan_cookie_write_flush (void *cookie);
|
|
||||||
assuan_error_t _assuan_write_line (assuan_context_t ctx, const char *prefix,
|
|
||||||
const char *line, size_t len);
|
|
||||||
|
|
||||||
/*-- assuan-client.c --*/
|
|
||||||
assuan_error_t _assuan_read_from_server (assuan_context_t ctx,
|
|
||||||
int *okay, int *off);
|
|
||||||
|
|
||||||
/*-- assuan-error.c --*/
|
|
||||||
|
|
||||||
/*-- assuan-inquire.c --*/
|
|
||||||
int _assuan_inquire_ext_cb (assuan_context_t ctx);
|
|
||||||
void _assuan_inquire_release (assuan_context_t ctx);
|
|
||||||
|
|
||||||
/* Map error codes as used in this implementation to the libgpg-error
|
|
||||||
codes. */
|
|
||||||
assuan_error_t _assuan_error (int oldcode);
|
|
||||||
/* Check if ERR means EAGAIN. */
|
|
||||||
int _assuan_error_is_eagain (assuan_error_t err);
|
|
||||||
|
|
||||||
/* Extract the error code from A. This works for both the old and the
|
|
||||||
new style error codes. This needs to be used whenever an error
|
|
||||||
code is compared. */
|
|
||||||
#define err_code(a) ((a) & 0x00ffffff)
|
|
||||||
|
|
||||||
/* Check whether A is the erro code for EOF. We allow for old and new
|
|
||||||
style EOF error codes here. */
|
|
||||||
#define err_is_eof(a) ((a) == (-1) || err_code (a) == 16383)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-- assuan-util.c --*/
|
|
||||||
void *_assuan_malloc (size_t n);
|
|
||||||
void *_assuan_calloc (size_t n, size_t m);
|
|
||||||
void *_assuan_realloc (void *p, size_t n);
|
|
||||||
void _assuan_free (void *p);
|
|
||||||
|
|
||||||
#define xtrymalloc(a) _assuan_malloc ((a))
|
|
||||||
#define xtrycalloc(a,b) _assuan_calloc ((a),(b))
|
|
||||||
#define xtryrealloc(a,b) _assuan_realloc((a),(b))
|
|
||||||
#define xfree(a) _assuan_free ((a))
|
|
||||||
|
|
||||||
#define set_error(c,e,t) \
|
|
||||||
assuan_set_error ((c), _assuan_error (ASSUAN_ ## e), (t))
|
|
||||||
|
|
||||||
#ifdef HAVE_W32_SYSTEM
|
|
||||||
const char *_assuan_w32_strerror (int ec);
|
|
||||||
#define w32_strerror(e) _assuan_w32_strerror ((e))
|
|
||||||
int _assuan_gpg_strerror_r (unsigned int err, char *buf, size_t buflen);
|
|
||||||
const char *_assuan_gpg_strsource (unsigned int err);
|
|
||||||
#endif /*HAVE_W32_SYSTEM*/
|
|
||||||
|
|
||||||
|
|
||||||
/*-- assuan-logging.c --*/
|
|
||||||
void _assuan_set_default_log_stream (FILE *fp);
|
|
||||||
|
|
||||||
void _assuan_log_printf (const char *format, ...)
|
|
||||||
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
|
|
||||||
__attribute__ ((format (printf,1,2)))
|
|
||||||
#endif
|
|
||||||
;
|
|
||||||
void _assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length);
|
|
||||||
void _assuan_log_sanitized_string (const char *string);
|
|
||||||
|
|
||||||
|
|
||||||
/*-- assuan-io.c --*/
|
|
||||||
pid_t _assuan_waitpid (pid_t pid, int *status, int options);
|
|
||||||
|
|
||||||
ssize_t _assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size);
|
|
||||||
ssize_t _assuan_simple_write (assuan_context_t ctx, const void *buffer,
|
|
||||||
size_t size);
|
|
||||||
ssize_t _assuan_io_read (assuan_fd_t fd, void *buffer, size_t size);
|
|
||||||
ssize_t _assuan_io_write (assuan_fd_t fd, const void *buffer, size_t size);
|
|
||||||
#ifdef HAVE_W32_SYSTEM
|
|
||||||
int _assuan_simple_sendmsg (assuan_context_t ctx, void *msg);
|
|
||||||
int _assuan_simple_recvmsg (assuan_context_t ctx, void *msg);
|
|
||||||
#else
|
|
||||||
ssize_t _assuan_simple_sendmsg (assuan_context_t ctx, struct msghdr *msg);
|
|
||||||
ssize_t _assuan_simple_recvmsg (assuan_context_t ctx, struct msghdr *msg);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void _assuan_usleep (unsigned int usec);
|
|
||||||
|
|
||||||
|
|
||||||
/*-- assuan-socket.c --*/
|
|
||||||
int _assuan_close (assuan_fd_t fd);
|
|
||||||
assuan_fd_t _assuan_sock_new (int domain, int type, int proto);
|
|
||||||
int _assuan_sock_connect (assuan_fd_t sockfd,
|
|
||||||
struct sockaddr *addr, int addrlen);
|
|
||||||
int _assuan_sock_bind (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen);
|
|
||||||
int _assuan_sock_get_nonce (struct sockaddr *addr, int addrlen,
|
|
||||||
assuan_sock_nonce_t *nonce);
|
|
||||||
int _assuan_sock_check_nonce (assuan_fd_t fd, assuan_sock_nonce_t *nonce);
|
|
||||||
#ifdef HAVE_W32_SYSTEM
|
|
||||||
int _assuan_sock_wsa2errno (int err);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_FOPENCOOKIE
|
|
||||||
/* We have to implement funopen in terms of glibc's fopencookie. */
|
|
||||||
FILE *_assuan_funopen(void *cookie,
|
|
||||||
cookie_read_function_t *readfn,
|
|
||||||
cookie_write_function_t *writefn,
|
|
||||||
cookie_seek_function_t *seekfn,
|
|
||||||
cookie_close_function_t *closefn);
|
|
||||||
#define funopen(a,r,w,s,c) _assuan_funopen ((a), (r), (w), (s), (c))
|
|
||||||
#endif /*HAVE_FOPENCOOKIE*/
|
|
||||||
|
|
||||||
/* Prototypes for replacement functions. */
|
|
||||||
#ifndef HAVE_MEMRCHR
|
|
||||||
void *memrchr (const void *block, int c, size_t size);
|
|
||||||
#endif
|
|
||||||
#ifndef HAVE_STPCPY
|
|
||||||
char *stpcpy (char *dest, const char *src);
|
|
||||||
#endif
|
|
||||||
#ifndef HAVE_SETENV
|
|
||||||
#define setenv _assuan_setenv
|
|
||||||
#define unsetenv _assuan_unsetenv
|
|
||||||
#define clearenv _assuan_clearenv
|
|
||||||
int setenv (const char *name, const char *value, int replace);
|
|
||||||
#endif
|
|
||||||
#ifndef HAVE_PUTC_UNLOCKED
|
|
||||||
int putc_unlocked (int c, FILE *stream);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define DIM(v) (sizeof(v)/sizeof((v)[0]))
|
|
||||||
#define DIMof(type,member) DIM(((type *)0)->member)
|
|
||||||
|
|
||||||
|
|
||||||
#if HAVE_W32_SYSTEM
|
|
||||||
#define SOCKET2HANDLE(s) ((void *)(s))
|
|
||||||
#define HANDLE2SOCKET(h) ((unsigned int)(h))
|
|
||||||
#else
|
|
||||||
#define SOCKET2HANDLE(s) (s)
|
|
||||||
#define HANDLE2SOCKET(h) (h)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif /*ASSUAN_DEFS_H*/
|
|
@ -1,915 +0,0 @@
|
|||||||
/* assuan-handler.c - dispatch commands
|
|
||||||
* Copyright (C) 2001, 2002, 2003, 2007 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include "assuan-defs.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define spacep(p) (*(p) == ' ' || *(p) == '\t')
|
|
||||||
#define digitp(a) ((a) >= '0' && (a) <= '9')
|
|
||||||
|
|
||||||
static int my_strcasecmp (const char *a, const char *b);
|
|
||||||
|
|
||||||
|
|
||||||
#define PROCESS_DONE(ctx, rc) \
|
|
||||||
((ctx)->in_process_next ? assuan_process_done ((ctx), (rc)) : (rc))
|
|
||||||
|
|
||||||
static int
|
|
||||||
dummy_handler (assuan_context_t ctx, char *line)
|
|
||||||
{
|
|
||||||
return
|
|
||||||
PROCESS_DONE (ctx, set_error (ctx, Server_Fault, "no handler registered"));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
std_handler_nop (assuan_context_t ctx, char *line)
|
|
||||||
{
|
|
||||||
return PROCESS_DONE (ctx, 0); /* okay */
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
std_handler_cancel (assuan_context_t ctx, char *line)
|
|
||||||
{
|
|
||||||
if (ctx->cancel_notify_fnc)
|
|
||||||
ctx->cancel_notify_fnc (ctx);
|
|
||||||
return PROCESS_DONE (ctx, set_error (ctx, Not_Implemented, NULL));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
std_handler_option (assuan_context_t ctx, char *line)
|
|
||||||
{
|
|
||||||
char *key, *value, *p;
|
|
||||||
|
|
||||||
for (key=line; spacep (key); key++)
|
|
||||||
;
|
|
||||||
if (!*key)
|
|
||||||
return
|
|
||||||
PROCESS_DONE (ctx, set_error (ctx, Syntax_Error, "argument required"));
|
|
||||||
if (*key == '=')
|
|
||||||
return
|
|
||||||
PROCESS_DONE (ctx, set_error (ctx, Syntax_Error,
|
|
||||||
"no option name given"));
|
|
||||||
for (value=key; *value && !spacep (value) && *value != '='; value++)
|
|
||||||
;
|
|
||||||
if (*value)
|
|
||||||
{
|
|
||||||
if (spacep (value))
|
|
||||||
*value++ = 0; /* terminate key */
|
|
||||||
for (; spacep (value); value++)
|
|
||||||
;
|
|
||||||
if (*value == '=')
|
|
||||||
{
|
|
||||||
*value++ = 0; /* terminate key */
|
|
||||||
for (; spacep (value); value++)
|
|
||||||
;
|
|
||||||
if (!*value)
|
|
||||||
return
|
|
||||||
PROCESS_DONE (ctx, set_error (ctx, Syntax_Error,
|
|
||||||
"option argument expected"));
|
|
||||||
}
|
|
||||||
if (*value)
|
|
||||||
{
|
|
||||||
for (p = value + strlen(value) - 1; p > value && spacep (p); p--)
|
|
||||||
;
|
|
||||||
if (p > value)
|
|
||||||
*++p = 0; /* strip trailing spaces */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*key == '-' && key[1] == '-' && key[2])
|
|
||||||
key += 2; /* the double dashes are optional */
|
|
||||||
if (*key == '-')
|
|
||||||
return PROCESS_DONE (ctx,
|
|
||||||
set_error (ctx, Syntax_Error,
|
|
||||||
"option should not begin with one dash"));
|
|
||||||
|
|
||||||
if (ctx->option_handler_fnc)
|
|
||||||
return PROCESS_DONE (ctx, ctx->option_handler_fnc (ctx, key, value));
|
|
||||||
return PROCESS_DONE (ctx, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
std_handler_bye (assuan_context_t ctx, char *line)
|
|
||||||
{
|
|
||||||
if (ctx->bye_notify_fnc)
|
|
||||||
ctx->bye_notify_fnc (ctx);
|
|
||||||
assuan_close_input_fd (ctx);
|
|
||||||
assuan_close_output_fd (ctx);
|
|
||||||
return PROCESS_DONE (ctx, _assuan_error (-1)); /* pretty simple :-) */
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
std_handler_auth (assuan_context_t ctx, char *line)
|
|
||||||
{
|
|
||||||
return PROCESS_DONE (ctx, set_error (ctx, Not_Implemented, NULL));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
std_handler_reset (assuan_context_t ctx, char *line)
|
|
||||||
{
|
|
||||||
if (ctx->reset_notify_fnc)
|
|
||||||
ctx->reset_notify_fnc (ctx);
|
|
||||||
assuan_close_input_fd (ctx);
|
|
||||||
assuan_close_output_fd (ctx);
|
|
||||||
_assuan_uds_close_fds (ctx);
|
|
||||||
return PROCESS_DONE (ctx, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
std_handler_help (assuan_context_t ctx, char *line)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
char buf[ASSUAN_LINELENGTH];
|
|
||||||
|
|
||||||
for (i = 0; i < ctx->cmdtbl_used; i++)
|
|
||||||
{
|
|
||||||
snprintf (buf, sizeof (buf), "# %s", ctx->cmdtbl[i].name);
|
|
||||||
buf[ASSUAN_LINELENGTH - 1] = '\0';
|
|
||||||
assuan_write_line (ctx, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
return PROCESS_DONE (ctx, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
std_handler_end (assuan_context_t ctx, char *line)
|
|
||||||
{
|
|
||||||
return PROCESS_DONE (ctx, set_error (ctx, Not_Implemented, NULL));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
assuan_error_t
|
|
||||||
assuan_command_parse_fd (assuan_context_t ctx, char *line, assuan_fd_t *rfd)
|
|
||||||
{
|
|
||||||
char *endp;
|
|
||||||
|
|
||||||
if ((strncmp (line, "FD", 2) && strncmp (line, "fd", 2))
|
|
||||||
|| (line[2] != '=' && line[2] != '\0' && !spacep(&line[2])))
|
|
||||||
return set_error (ctx, Syntax_Error, "FD[=<n>] expected");
|
|
||||||
line += 2;
|
|
||||||
if (*line == '=')
|
|
||||||
{
|
|
||||||
line ++;
|
|
||||||
if (!digitp (*line))
|
|
||||||
return set_error (ctx, Syntax_Error, "number required");
|
|
||||||
#ifdef HAVE_W32_SYSTEM
|
|
||||||
/* Fixme: For a W32/64bit system we will need to change the cast
|
|
||||||
and the conversion fucntion. */
|
|
||||||
*rfd = (void*)strtoul (line, &endp, 10);
|
|
||||||
#else
|
|
||||||
*rfd = strtoul (line, &endp, 10);
|
|
||||||
#endif
|
|
||||||
/* Remove that argument so that a notify handler won't see it. */
|
|
||||||
memset (line, ' ', endp? (endp-line):strlen(line));
|
|
||||||
|
|
||||||
if (*rfd == ctx->inbound.fd)
|
|
||||||
return set_error (ctx, Parameter_Conflict, "fd same as inbound fd");
|
|
||||||
if (*rfd == ctx->outbound.fd)
|
|
||||||
return set_error (ctx, Parameter_Conflict, "fd same as outbound fd");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
/* Our peer has sent the file descriptor. */
|
|
||||||
return assuan_receivefd (ctx, rfd);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Format is INPUT FD=<n> */
|
|
||||||
static int
|
|
||||||
std_handler_input (assuan_context_t ctx, char *line)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
assuan_fd_t fd;
|
|
||||||
|
|
||||||
rc = assuan_command_parse_fd (ctx, line, &fd);
|
|
||||||
if (rc)
|
|
||||||
return PROCESS_DONE (ctx, rc);
|
|
||||||
ctx->input_fd = fd;
|
|
||||||
if (ctx->input_notify_fnc)
|
|
||||||
ctx->input_notify_fnc (ctx, line);
|
|
||||||
return PROCESS_DONE (ctx, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Format is OUTPUT FD=<n> */
|
|
||||||
static int
|
|
||||||
std_handler_output (assuan_context_t ctx, char *line)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
assuan_fd_t fd;
|
|
||||||
|
|
||||||
rc = assuan_command_parse_fd (ctx, line, &fd);
|
|
||||||
if (rc)
|
|
||||||
return PROCESS_DONE (ctx, rc);
|
|
||||||
ctx->output_fd = fd;
|
|
||||||
if (ctx->output_notify_fnc)
|
|
||||||
ctx->output_notify_fnc (ctx, line);
|
|
||||||
return PROCESS_DONE (ctx, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* This is a table with the standard commands and handler for them.
|
|
||||||
The table is used to initialize a new context and associate strings
|
|
||||||
with default handlers */
|
|
||||||
static struct {
|
|
||||||
const char *name;
|
|
||||||
int (*handler)(assuan_context_t, char *line);
|
|
||||||
int always; /* always initialize this command */
|
|
||||||
} std_cmd_table[] = {
|
|
||||||
{ "NOP", std_handler_nop, 1 },
|
|
||||||
{ "CANCEL", std_handler_cancel, 1 },
|
|
||||||
{ "OPTION", std_handler_option, 1 },
|
|
||||||
{ "BYE", std_handler_bye, 1 },
|
|
||||||
{ "AUTH", std_handler_auth, 1 },
|
|
||||||
{ "RESET", std_handler_reset, 1 },
|
|
||||||
{ "END", std_handler_end, 1 },
|
|
||||||
{ "HELP", std_handler_help, 1 },
|
|
||||||
|
|
||||||
{ "INPUT", std_handler_input, 0 },
|
|
||||||
{ "OUTPUT", std_handler_output, 0 },
|
|
||||||
{ "OPTION", std_handler_option, 1 },
|
|
||||||
{ NULL, NULL, 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* assuan_register_command:
|
|
||||||
* @ctx: the server context
|
|
||||||
* @cmd_name: A string with the command name
|
|
||||||
* @handler: The handler function to be called or NULL to use a default
|
|
||||||
* handler.
|
|
||||||
*
|
|
||||||
* Register a handler to be used for a given command. Note that
|
|
||||||
* several default handlers are already regsitered with a new context.
|
|
||||||
* This function however allows to override them.
|
|
||||||
*
|
|
||||||
* Return value: 0 on success or an error code
|
|
||||||
**/
|
|
||||||
int
|
|
||||||
assuan_register_command (assuan_context_t ctx,
|
|
||||||
const char *cmd_name,
|
|
||||||
int (*handler)(assuan_context_t, char *))
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
const char *s;
|
|
||||||
|
|
||||||
if (cmd_name && !*cmd_name)
|
|
||||||
cmd_name = NULL;
|
|
||||||
|
|
||||||
if (!cmd_name)
|
|
||||||
return _assuan_error (ASSUAN_Invalid_Value);
|
|
||||||
|
|
||||||
if (!handler)
|
|
||||||
{ /* find a default handler. */
|
|
||||||
for (i=0; (s=std_cmd_table[i].name) && strcmp (cmd_name, s); i++)
|
|
||||||
;
|
|
||||||
if (!s)
|
|
||||||
{ /* Try again but case insensitive. */
|
|
||||||
for (i=0; (s=std_cmd_table[i].name)
|
|
||||||
&& my_strcasecmp (cmd_name, s); i++)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
if (s)
|
|
||||||
handler = std_cmd_table[i].handler;
|
|
||||||
if (!handler)
|
|
||||||
handler = dummy_handler; /* Last resort is the dummy handler. */
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ctx->cmdtbl)
|
|
||||||
{
|
|
||||||
ctx->cmdtbl_size = 50;
|
|
||||||
ctx->cmdtbl = xtrycalloc ( ctx->cmdtbl_size, sizeof *ctx->cmdtbl);
|
|
||||||
if (!ctx->cmdtbl)
|
|
||||||
return _assuan_error (ASSUAN_Out_Of_Core);
|
|
||||||
ctx->cmdtbl_used = 0;
|
|
||||||
}
|
|
||||||
else if (ctx->cmdtbl_used >= ctx->cmdtbl_size)
|
|
||||||
{
|
|
||||||
struct cmdtbl_s *x;
|
|
||||||
|
|
||||||
x = xtryrealloc ( ctx->cmdtbl, (ctx->cmdtbl_size+10) * sizeof *x);
|
|
||||||
if (!x)
|
|
||||||
return _assuan_error (ASSUAN_Out_Of_Core);
|
|
||||||
ctx->cmdtbl = x;
|
|
||||||
ctx->cmdtbl_size += 50;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->cmdtbl[ctx->cmdtbl_used].name = cmd_name;
|
|
||||||
ctx->cmdtbl[ctx->cmdtbl_used].handler = handler;
|
|
||||||
ctx->cmdtbl_used++;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
assuan_register_post_cmd_notify (assuan_context_t ctx,
|
|
||||||
void (*fnc)(assuan_context_t, int))
|
|
||||||
{
|
|
||||||
if (!ctx)
|
|
||||||
return _assuan_error (ASSUAN_Invalid_Value);
|
|
||||||
ctx->post_cmd_notify_fnc = fnc;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
assuan_register_bye_notify (assuan_context_t ctx,
|
|
||||||
void (*fnc)(assuan_context_t))
|
|
||||||
{
|
|
||||||
if (!ctx)
|
|
||||||
return _assuan_error (ASSUAN_Invalid_Value);
|
|
||||||
ctx->bye_notify_fnc = fnc;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
assuan_register_reset_notify (assuan_context_t ctx,
|
|
||||||
void (*fnc)(assuan_context_t))
|
|
||||||
{
|
|
||||||
if (!ctx)
|
|
||||||
return _assuan_error (ASSUAN_Invalid_Value);
|
|
||||||
ctx->reset_notify_fnc = fnc;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
assuan_register_cancel_notify (assuan_context_t ctx,
|
|
||||||
void (*fnc)(assuan_context_t))
|
|
||||||
{
|
|
||||||
if (!ctx)
|
|
||||||
return _assuan_error (ASSUAN_Invalid_Value);
|
|
||||||
ctx->cancel_notify_fnc = fnc;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
assuan_register_option_handler (assuan_context_t ctx,
|
|
||||||
int (*fnc)(assuan_context_t,
|
|
||||||
const char*, const char*))
|
|
||||||
{
|
|
||||||
if (!ctx)
|
|
||||||
return _assuan_error (ASSUAN_Invalid_Value);
|
|
||||||
ctx->option_handler_fnc = fnc;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
assuan_register_input_notify (assuan_context_t ctx,
|
|
||||||
void (*fnc)(assuan_context_t, const char *))
|
|
||||||
{
|
|
||||||
if (!ctx)
|
|
||||||
return _assuan_error (ASSUAN_Invalid_Value);
|
|
||||||
ctx->input_notify_fnc = fnc;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
assuan_register_output_notify (assuan_context_t ctx,
|
|
||||||
void (*fnc)(assuan_context_t, const char *))
|
|
||||||
{
|
|
||||||
if (!ctx)
|
|
||||||
return _assuan_error (ASSUAN_Invalid_Value);
|
|
||||||
ctx->output_notify_fnc = fnc;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Helper to register the standards commands */
|
|
||||||
int
|
|
||||||
_assuan_register_std_commands (assuan_context_t ctx)
|
|
||||||
{
|
|
||||||
int i, rc;
|
|
||||||
|
|
||||||
for (i=0; std_cmd_table[i].name; i++)
|
|
||||||
{
|
|
||||||
if (std_cmd_table[i].always)
|
|
||||||
{
|
|
||||||
rc = assuan_register_command (ctx, std_cmd_table[i].name, NULL);
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Process the special data lines. The "D " has already been removed
|
|
||||||
from the line. As all handlers this function may modify the line. */
|
|
||||||
static int
|
|
||||||
handle_data_line (assuan_context_t ctx, char *line, int linelen)
|
|
||||||
{
|
|
||||||
return set_error (ctx, Not_Implemented, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* like ascii_strcasecmp but assume that B is already uppercase */
|
|
||||||
static int
|
|
||||||
my_strcasecmp (const char *a, const char *b)
|
|
||||||
{
|
|
||||||
if (a == b)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
for (; *a && *b; a++, b++)
|
|
||||||
{
|
|
||||||
if (((*a >= 'a' && *a <= 'z')? (*a&~0x20):*a) != *b)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return *a == *b? 0 : (((*a >= 'a' && *a <= 'z')? (*a&~0x20):*a) - *b);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Parse the line, break out the command, find it in the command
|
|
||||||
table, remove leading and white spaces from the arguments, call the
|
|
||||||
handler with the argument line and return the error. */
|
|
||||||
static int
|
|
||||||
dispatch_command (assuan_context_t ctx, char *line, int linelen)
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
const char *s;
|
|
||||||
int shift, i;
|
|
||||||
|
|
||||||
/* Note that as this function is invoked by assuan_process_next as
|
|
||||||
well, we need to hide non-critical errors with PROCESS_DONE. */
|
|
||||||
|
|
||||||
if (*line == 'D' && line[1] == ' ') /* divert to special handler */
|
|
||||||
/* FIXME: Depending on the final implementation of
|
|
||||||
handle_data_line, this may be wrong here. For example, if a
|
|
||||||
user callback is invoked, and that callback is responsible for
|
|
||||||
calling assuan_process_done, then this is wrong. */
|
|
||||||
return PROCESS_DONE (ctx, handle_data_line (ctx, line+2, linelen-2));
|
|
||||||
|
|
||||||
for (p=line; *p && *p != ' ' && *p != '\t'; p++)
|
|
||||||
;
|
|
||||||
if (p==line)
|
|
||||||
return PROCESS_DONE
|
|
||||||
(ctx, set_error (ctx, Syntax_Error, "leading white-space"));
|
|
||||||
if (*p)
|
|
||||||
{ /* Skip over leading WS after the keyword */
|
|
||||||
*p++ = 0;
|
|
||||||
while ( *p == ' ' || *p == '\t')
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
shift = p - line;
|
|
||||||
|
|
||||||
for (i=0; (s=ctx->cmdtbl[i].name); i++)
|
|
||||||
{
|
|
||||||
if (!strcmp (line, s))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!s)
|
|
||||||
{ /* and try case insensitive */
|
|
||||||
for (i=0; (s=ctx->cmdtbl[i].name); i++)
|
|
||||||
{
|
|
||||||
if (!my_strcasecmp (line, s))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!s)
|
|
||||||
return PROCESS_DONE (ctx, set_error (ctx, Unknown_Command, NULL));
|
|
||||||
line += shift;
|
|
||||||
linelen -= shift;
|
|
||||||
|
|
||||||
/* fprintf (stderr, "DBG-assuan: processing %s `%s'\n", s, line); */
|
|
||||||
return ctx->cmdtbl[i].handler (ctx, line);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Call this to acknowledge the current command. */
|
|
||||||
int
|
|
||||||
assuan_process_done (assuan_context_t ctx, int rc)
|
|
||||||
{
|
|
||||||
if (!ctx->in_command)
|
|
||||||
return _assuan_error (ASSUAN_General_Error);
|
|
||||||
|
|
||||||
ctx->in_command = 0;
|
|
||||||
|
|
||||||
/* Check for data write errors. */
|
|
||||||
if (ctx->outbound.data.fp)
|
|
||||||
{
|
|
||||||
/* Flush the data lines. */
|
|
||||||
fclose (ctx->outbound.data.fp);
|
|
||||||
ctx->outbound.data.fp = NULL;
|
|
||||||
if (!rc && ctx->outbound.data.error)
|
|
||||||
rc = ctx->outbound.data.error;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Flush any data send without using the data FP. */
|
|
||||||
assuan_send_data (ctx, NULL, 0);
|
|
||||||
if (!rc && ctx->outbound.data.error)
|
|
||||||
rc = ctx->outbound.data.error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Error handling. */
|
|
||||||
if (!rc)
|
|
||||||
{
|
|
||||||
rc = assuan_write_line (ctx, ctx->okay_line? ctx->okay_line : "OK");
|
|
||||||
}
|
|
||||||
else if (err_is_eof (rc))
|
|
||||||
{ /* No error checking because the peer may have already disconnect. */
|
|
||||||
assuan_write_line (ctx, "OK closing connection");
|
|
||||||
ctx->finish_handler (ctx);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char errline[300];
|
|
||||||
|
|
||||||
if (rc < 100)
|
|
||||||
sprintf (errline, "ERR %d server fault (%.50s)",
|
|
||||||
_assuan_error (ASSUAN_Server_Fault), assuan_strerror (rc));
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const char *text = ctx->err_no == rc? ctx->err_str:NULL;
|
|
||||||
|
|
||||||
#if defined(HAVE_W32_SYSTEM)
|
|
||||||
unsigned int source, code;
|
|
||||||
char ebuf[50];
|
|
||||||
const char *esrc;
|
|
||||||
|
|
||||||
source = ((rc >> 24) & 0xff);
|
|
||||||
code = (rc & 0x00ffffff);
|
|
||||||
if (source
|
|
||||||
&& !_assuan_gpg_strerror_r (rc, ebuf, sizeof ebuf)
|
|
||||||
&& (esrc=_assuan_gpg_strsource (rc)))
|
|
||||||
{
|
|
||||||
/* Assume this is an libgpg-error. */
|
|
||||||
sprintf (errline, "ERR %d %.50s <%.30s>%s%.100s",
|
|
||||||
rc, ebuf, esrc,
|
|
||||||
text? " - ":"", text?text:"");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#elif defined(__GNUC__) && defined(__ELF__)
|
|
||||||
/* If we have weak symbol support we try to use the error
|
|
||||||
strings from libgpg-error without creating a dependency.
|
|
||||||
They are used for debugging purposes only, so there is no
|
|
||||||
problem if they are not available. We need to make sure
|
|
||||||
that we are using ELF because only this guarantees that
|
|
||||||
weak symbol support is available in case GNU ld is not
|
|
||||||
used. It seems that old gcc versions don't implement the
|
|
||||||
weak attribute properly but it works with the weak
|
|
||||||
pragma. */
|
|
||||||
|
|
||||||
unsigned int source, code;
|
|
||||||
|
|
||||||
int gpg_strerror_r (unsigned int err, char *buf, size_t buflen)
|
|
||||||
__attribute__ ((weak));
|
|
||||||
const char *gpg_strsource (unsigned int err)
|
|
||||||
__attribute__ ((weak));
|
|
||||||
#if __GNUC__ < 3
|
|
||||||
#pragma weak gpg_strerror_r
|
|
||||||
#pragma weak gpg_strsource
|
|
||||||
#endif
|
|
||||||
|
|
||||||
source = ((rc >> 24) & 0xff);
|
|
||||||
code = (rc & 0x00ffffff);
|
|
||||||
if (source && gpg_strsource && gpg_strerror_r)
|
|
||||||
{
|
|
||||||
/* Assume this is an libgpg-error. */
|
|
||||||
char ebuf[50];
|
|
||||||
|
|
||||||
gpg_strerror_r (rc, ebuf, sizeof ebuf );
|
|
||||||
sprintf (errline, "ERR %d %.50s <%.30s>%s%.100s",
|
|
||||||
rc,
|
|
||||||
ebuf,
|
|
||||||
gpg_strsource (rc),
|
|
||||||
text? " - ":"", text?text:"");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif /* __GNUC__ && __ELF__ */
|
|
||||||
sprintf (errline, "ERR %d %.50s%s%.100s",
|
|
||||||
rc, assuan_strerror (rc), text? " - ":"", text?text:"");
|
|
||||||
}
|
|
||||||
rc = assuan_write_line (ctx, errline);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx->post_cmd_notify_fnc)
|
|
||||||
ctx->post_cmd_notify_fnc (ctx, rc);
|
|
||||||
|
|
||||||
ctx->confidential = 0;
|
|
||||||
if (ctx->okay_line)
|
|
||||||
{
|
|
||||||
xfree (ctx->okay_line);
|
|
||||||
ctx->okay_line = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
process_next (assuan_context_t ctx)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
/* What the next thing to do is depends on the current state.
|
|
||||||
However, we will always first read the next line. The client is
|
|
||||||
required to write full lines without blocking long after starting
|
|
||||||
a partial line. */
|
|
||||||
rc = _assuan_read_line (ctx);
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
if (*ctx->inbound.line == '#' || !ctx->inbound.linelen)
|
|
||||||
/* Comment lines are ignored. */
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Now we have a line that really means something. It could be one
|
|
||||||
of the following things: First, if we are not in a command
|
|
||||||
already, it is the next command to dispatch. Second, if we are
|
|
||||||
in a command, it can only be the response to an INQUIRE
|
|
||||||
reply. */
|
|
||||||
|
|
||||||
if (!ctx->in_command)
|
|
||||||
{
|
|
||||||
ctx->in_command = 1;
|
|
||||||
|
|
||||||
ctx->outbound.data.error = 0;
|
|
||||||
ctx->outbound.data.linelen = 0;
|
|
||||||
/* Dispatch command and return reply. */
|
|
||||||
ctx->in_process_next = 1;
|
|
||||||
rc = dispatch_command (ctx, ctx->inbound.line, ctx->inbound.linelen);
|
|
||||||
ctx->in_process_next = 0;
|
|
||||||
}
|
|
||||||
else if (ctx->in_inquire)
|
|
||||||
{
|
|
||||||
/* FIXME: Pick up the continuation. */
|
|
||||||
rc = _assuan_inquire_ext_cb (ctx);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Should not happen. The client is sending data while we are
|
|
||||||
in a command and not waiting for an inquire. We log an error
|
|
||||||
and discard it. */
|
|
||||||
_assuan_log_printf ("unexpected client data\n");
|
|
||||||
rc = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* This function should be invoked when the assuan connected FD is
|
|
||||||
ready for reading. If the equivalent to EWOULDBLOCK is returned
|
|
||||||
(this should be done by the command handler), assuan_process_next
|
|
||||||
should be invoked the next time the connected FD is readable.
|
|
||||||
Eventually, the caller will finish by invoking
|
|
||||||
assuan_process_done. */
|
|
||||||
int
|
|
||||||
assuan_process_next (assuan_context_t ctx)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
rc = process_next (ctx);
|
|
||||||
}
|
|
||||||
while (!rc && assuan_pending_line (ctx));
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
process_request (assuan_context_t ctx)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
if (ctx->in_inquire)
|
|
||||||
return _assuan_error (ASSUAN_Nested_Commands);
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
rc = _assuan_read_line (ctx);
|
|
||||||
}
|
|
||||||
while (_assuan_error_is_eagain (rc));
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
if (*ctx->inbound.line == '#' || !ctx->inbound.linelen)
|
|
||||||
return 0; /* comment line - ignore */
|
|
||||||
|
|
||||||
ctx->in_command = 1;
|
|
||||||
ctx->outbound.data.error = 0;
|
|
||||||
ctx->outbound.data.linelen = 0;
|
|
||||||
/* dispatch command and return reply */
|
|
||||||
rc = dispatch_command (ctx, ctx->inbound.line, ctx->inbound.linelen);
|
|
||||||
|
|
||||||
return assuan_process_done (ctx, rc);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* assuan_process:
|
|
||||||
* @ctx: assuan context
|
|
||||||
*
|
|
||||||
* This function is used to handle the assuan protocol after a
|
|
||||||
* connection has been established using assuan_accept(). This is the
|
|
||||||
* main protocol handler.
|
|
||||||
*
|
|
||||||
* Return value: 0 on success or an error code if the assuan operation
|
|
||||||
* failed. Note, that no error is returned for operational errors.
|
|
||||||
**/
|
|
||||||
int
|
|
||||||
assuan_process (assuan_context_t ctx)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
do {
|
|
||||||
rc = process_request (ctx);
|
|
||||||
} while (!rc);
|
|
||||||
|
|
||||||
if (err_is_eof (rc))
|
|
||||||
rc = 0;
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* assuan_get_active_fds:
|
|
||||||
* @ctx: Assuan context
|
|
||||||
* @what: 0 for read fds, 1 for write fds
|
|
||||||
* @fdarray: Caller supplied array to store the FDs
|
|
||||||
* @fdarraysize: size of that array
|
|
||||||
*
|
|
||||||
* Return all active filedescriptors for the given context. This
|
|
||||||
* function can be used to select on the fds and call
|
|
||||||
* assuan_process_next() if there is an active one. The first fd in
|
|
||||||
* the array is the one used for the command connection.
|
|
||||||
*
|
|
||||||
* Note, that write FDs are not yet supported.
|
|
||||||
*
|
|
||||||
* Return value: number of FDs active and put into @fdarray or -1 on
|
|
||||||
* error which is most likely a too small fdarray.
|
|
||||||
**/
|
|
||||||
int
|
|
||||||
assuan_get_active_fds (assuan_context_t ctx, int what,
|
|
||||||
assuan_fd_t *fdarray, int fdarraysize)
|
|
||||||
{
|
|
||||||
int n = 0;
|
|
||||||
|
|
||||||
if (!ctx || fdarraysize < 2 || what < 0 || what > 1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (!what)
|
|
||||||
{
|
|
||||||
if (ctx->inbound.fd != ASSUAN_INVALID_FD)
|
|
||||||
fdarray[n++] = ctx->inbound.fd;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (ctx->outbound.fd != ASSUAN_INVALID_FD)
|
|
||||||
fdarray[n++] = ctx->outbound.fd;
|
|
||||||
if (ctx->outbound.data.fp)
|
|
||||||
#ifdef HAVE_W32_SYSTEM
|
|
||||||
fdarray[n++] = (void*)_get_osfhandle (fileno (ctx->outbound.data.fp));
|
|
||||||
#else
|
|
||||||
fdarray[n++] = fileno (ctx->outbound.data.fp);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Two simple wrappers to make the expected function types match. */
|
|
||||||
#ifdef HAVE_FUNOPEN
|
|
||||||
static int
|
|
||||||
fun1_cookie_write (void *cookie, const char *buffer, int orig_size)
|
|
||||||
{
|
|
||||||
return _assuan_cookie_write_data (cookie, buffer, orig_size);
|
|
||||||
}
|
|
||||||
#endif /*HAVE_FUNOPEN*/
|
|
||||||
#ifdef HAVE_FOPENCOOKIE
|
|
||||||
static ssize_t
|
|
||||||
fun2_cookie_write (void *cookie, const char *buffer, size_t orig_size)
|
|
||||||
{
|
|
||||||
return _assuan_cookie_write_data (cookie, buffer, orig_size);
|
|
||||||
}
|
|
||||||
#endif /*HAVE_FOPENCOOKIE*/
|
|
||||||
|
|
||||||
/* Return a FP to be used for data output. The FILE pointer is valid
|
|
||||||
until the end of a handler. So a close is not needed. Assuan does
|
|
||||||
all the buffering needed to insert the status line as well as the
|
|
||||||
required line wappping and quoting for data lines.
|
|
||||||
|
|
||||||
We use GNU's custom streams here. There should be an alternative
|
|
||||||
implementaion for systems w/o a glibc, a simple implementation
|
|
||||||
could use a child process */
|
|
||||||
FILE *
|
|
||||||
assuan_get_data_fp (assuan_context_t ctx)
|
|
||||||
{
|
|
||||||
#if defined (HAVE_FOPENCOOKIE) || defined (HAVE_FUNOPEN)
|
|
||||||
if (ctx->outbound.data.fp)
|
|
||||||
return ctx->outbound.data.fp;
|
|
||||||
|
|
||||||
#ifdef HAVE_FUNOPEN
|
|
||||||
ctx->outbound.data.fp = funopen (ctx, 0, fun1_cookie_write,
|
|
||||||
0, _assuan_cookie_write_flush);
|
|
||||||
#else
|
|
||||||
ctx->outbound.data.fp = funopen (ctx, 0, fun2_cookie_write,
|
|
||||||
0, _assuan_cookie_write_flush);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ctx->outbound.data.error = 0;
|
|
||||||
return ctx->outbound.data.fp;
|
|
||||||
#else
|
|
||||||
errno = ENOSYS;
|
|
||||||
return NULL;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Set the text used for the next OK reponse. This string is
|
|
||||||
automatically reset to NULL after the next command. */
|
|
||||||
assuan_error_t
|
|
||||||
assuan_set_okay_line (assuan_context_t ctx, const char *line)
|
|
||||||
{
|
|
||||||
if (!ctx)
|
|
||||||
return _assuan_error (ASSUAN_Invalid_Value);
|
|
||||||
if (!line)
|
|
||||||
{
|
|
||||||
xfree (ctx->okay_line);
|
|
||||||
ctx->okay_line = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* FIXME: we need to use gcry_is_secure() to test whether
|
|
||||||
we should allocate the entire line in secure memory */
|
|
||||||
char *buf = xtrymalloc (3+strlen(line)+1);
|
|
||||||
if (!buf)
|
|
||||||
return _assuan_error (ASSUAN_Out_Of_Core);
|
|
||||||
strcpy (buf, "OK ");
|
|
||||||
strcpy (buf+3, line);
|
|
||||||
xfree (ctx->okay_line);
|
|
||||||
ctx->okay_line = buf;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
assuan_error_t
|
|
||||||
assuan_write_status (assuan_context_t ctx,
|
|
||||||
const char *keyword, const char *text)
|
|
||||||
{
|
|
||||||
char buffer[256];
|
|
||||||
char *helpbuf;
|
|
||||||
size_t n;
|
|
||||||
assuan_error_t ae;
|
|
||||||
|
|
||||||
if ( !ctx || !keyword)
|
|
||||||
return _assuan_error (ASSUAN_Invalid_Value);
|
|
||||||
if (!text)
|
|
||||||
text = "";
|
|
||||||
|
|
||||||
n = 2 + strlen (keyword) + 1 + strlen (text) + 1;
|
|
||||||
if (n < sizeof (buffer))
|
|
||||||
{
|
|
||||||
strcpy (buffer, "S ");
|
|
||||||
strcat (buffer, keyword);
|
|
||||||
if (*text)
|
|
||||||
{
|
|
||||||
strcat (buffer, " ");
|
|
||||||
strcat (buffer, text);
|
|
||||||
}
|
|
||||||
ae = assuan_write_line (ctx, buffer);
|
|
||||||
}
|
|
||||||
else if ( (helpbuf = xtrymalloc (n)) )
|
|
||||||
{
|
|
||||||
strcpy (helpbuf, "S ");
|
|
||||||
strcat (helpbuf, keyword);
|
|
||||||
if (*text)
|
|
||||||
{
|
|
||||||
strcat (helpbuf, " ");
|
|
||||||
strcat (helpbuf, text);
|
|
||||||
}
|
|
||||||
ae = assuan_write_line (ctx, helpbuf);
|
|
||||||
xfree (helpbuf);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ae = 0;
|
|
||||||
return ae;
|
|
||||||
}
|
|
@ -1,385 +0,0 @@
|
|||||||
/* assuan-inquire.c - handle inquire stuff
|
|
||||||
* Copyright (C) 2001, 2002, 2003, 2005, 2007 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "assuan-defs.h"
|
|
||||||
|
|
||||||
#define digitp(a) ((a) >= '0' && (a) <= '9')
|
|
||||||
#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
|
|
||||||
*(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
|
|
||||||
#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
|
|
||||||
|
|
||||||
|
|
||||||
struct membuf
|
|
||||||
{
|
|
||||||
size_t len;
|
|
||||||
size_t size;
|
|
||||||
char *buf;
|
|
||||||
int out_of_core;
|
|
||||||
int too_large;
|
|
||||||
size_t maxlen;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* A simple implementation of a dynamic buffer. Use init_membuf() to
|
|
||||||
create a buffer, put_membuf to append bytes and get_membuf to
|
|
||||||
release and return the buffer. Allocation errors are detected but
|
|
||||||
only returned at the final get_membuf(), this helps not to clutter
|
|
||||||
the code with out of core checks. */
|
|
||||||
|
|
||||||
static void
|
|
||||||
init_membuf (struct membuf *mb, int initiallen, size_t maxlen)
|
|
||||||
{
|
|
||||||
mb->len = 0;
|
|
||||||
mb->size = initiallen;
|
|
||||||
mb->out_of_core = 0;
|
|
||||||
mb->too_large = 0;
|
|
||||||
mb->maxlen = maxlen;
|
|
||||||
/* we need to allocate one byte more for get_membuf */
|
|
||||||
mb->buf = xtrymalloc (initiallen+1);
|
|
||||||
if (!mb->buf)
|
|
||||||
mb->out_of_core = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
put_membuf (struct membuf *mb, const void *buf, size_t len)
|
|
||||||
{
|
|
||||||
if (mb->out_of_core || mb->too_large)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (mb->maxlen && mb->len + len > mb->maxlen)
|
|
||||||
{
|
|
||||||
mb->too_large = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mb->len + len >= mb->size)
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
mb->size += len + 1024;
|
|
||||||
/* we need to allocate one byte more for get_membuf */
|
|
||||||
p = xtryrealloc (mb->buf, mb->size+1);
|
|
||||||
if (!p)
|
|
||||||
{
|
|
||||||
mb->out_of_core = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mb->buf = p;
|
|
||||||
}
|
|
||||||
memcpy (mb->buf + mb->len, buf, len);
|
|
||||||
mb->len += len;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *
|
|
||||||
get_membuf (struct membuf *mb, size_t *len)
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
if (mb->out_of_core || mb->too_large)
|
|
||||||
{
|
|
||||||
xfree (mb->buf);
|
|
||||||
mb->buf = NULL;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
mb->buf[mb->len] = 0; /* there is enough space for the hidden eos */
|
|
||||||
p = mb->buf;
|
|
||||||
*len = mb->len;
|
|
||||||
mb->buf = NULL;
|
|
||||||
mb->out_of_core = 1; /* don't allow a reuse */
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
free_membuf (struct membuf *mb)
|
|
||||||
{
|
|
||||||
xfree (mb->buf);
|
|
||||||
mb->buf = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* assuan_inquire:
|
|
||||||
* @ctx: An assuan context
|
|
||||||
* @keyword: The keyword used for the inquire
|
|
||||||
* @r_buffer: Returns an allocated buffer
|
|
||||||
* @r_length: Returns the length of this buffer
|
|
||||||
* @maxlen: If not 0, the size limit of the inquired data.
|
|
||||||
*
|
|
||||||
* A Server may use this to Send an inquire. r_buffer, r_length and
|
|
||||||
* maxlen may all be NULL/0 to indicate that no real data is expected.
|
|
||||||
*
|
|
||||||
* Return value: 0 on success or an ASSUAN error code
|
|
||||||
**/
|
|
||||||
assuan_error_t
|
|
||||||
assuan_inquire (assuan_context_t ctx, const char *keyword,
|
|
||||||
unsigned char **r_buffer, size_t *r_length, size_t maxlen)
|
|
||||||
{
|
|
||||||
assuan_error_t rc;
|
|
||||||
struct membuf mb;
|
|
||||||
char cmdbuf[LINELENGTH-10]; /* (10 = strlen ("INQUIRE ")+CR,LF) */
|
|
||||||
unsigned char *line, *p;
|
|
||||||
int linelen;
|
|
||||||
int nodataexpected;
|
|
||||||
|
|
||||||
if (!ctx || !keyword || (10 + strlen (keyword) >= sizeof (cmdbuf)))
|
|
||||||
return _assuan_error (ASSUAN_Invalid_Value);
|
|
||||||
nodataexpected = !r_buffer && !r_length && !maxlen;
|
|
||||||
if (!nodataexpected && (!r_buffer || !r_length))
|
|
||||||
return _assuan_error (ASSUAN_Invalid_Value);
|
|
||||||
if (!ctx->is_server)
|
|
||||||
return _assuan_error (ASSUAN_Not_A_Server);
|
|
||||||
if (ctx->in_inquire)
|
|
||||||
return _assuan_error (ASSUAN_Nested_Commands);
|
|
||||||
|
|
||||||
ctx->in_inquire = 1;
|
|
||||||
if (nodataexpected)
|
|
||||||
memset (&mb, 0, sizeof mb); /* avoid compiler warnings */
|
|
||||||
else
|
|
||||||
init_membuf (&mb, maxlen? maxlen:1024, maxlen);
|
|
||||||
|
|
||||||
strcpy (stpcpy (cmdbuf, "INQUIRE "), keyword);
|
|
||||||
rc = assuan_write_line (ctx, cmdbuf);
|
|
||||||
if (rc)
|
|
||||||
goto leave;
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
rc = _assuan_read_line (ctx);
|
|
||||||
if (rc)
|
|
||||||
goto leave;
|
|
||||||
line = (unsigned char *) ctx->inbound.line;
|
|
||||||
linelen = ctx->inbound.linelen;
|
|
||||||
}
|
|
||||||
while (*line == '#' || !linelen);
|
|
||||||
if (line[0] == 'E' && line[1] == 'N' && line[2] == 'D'
|
|
||||||
&& (!line[3] || line[3] == ' '))
|
|
||||||
break; /* END command received*/
|
|
||||||
if (line[0] == 'C' && line[1] == 'A' && line[2] == 'N')
|
|
||||||
{
|
|
||||||
rc = _assuan_error (ASSUAN_Canceled);
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
if (line[0] != 'D' || line[1] != ' ' || nodataexpected)
|
|
||||||
{
|
|
||||||
rc = _assuan_error (ASSUAN_Unexpected_Command);
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
if (linelen < 3)
|
|
||||||
continue;
|
|
||||||
line += 2;
|
|
||||||
linelen -= 2;
|
|
||||||
|
|
||||||
p = line;
|
|
||||||
while (linelen)
|
|
||||||
{
|
|
||||||
for (;linelen && *p != '%'; linelen--, p++)
|
|
||||||
;
|
|
||||||
put_membuf (&mb, line, p-line);
|
|
||||||
if (linelen > 2)
|
|
||||||
{ /* handle escaping */
|
|
||||||
unsigned char tmp[1];
|
|
||||||
p++;
|
|
||||||
*tmp = xtoi_2 (p);
|
|
||||||
p += 2;
|
|
||||||
linelen -= 3;
|
|
||||||
put_membuf (&mb, tmp, 1);
|
|
||||||
}
|
|
||||||
line = p;
|
|
||||||
}
|
|
||||||
if (mb.too_large)
|
|
||||||
{
|
|
||||||
rc = _assuan_error (ASSUAN_Too_Much_Data);
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!nodataexpected)
|
|
||||||
{
|
|
||||||
*r_buffer = get_membuf (&mb, r_length);
|
|
||||||
if (!*r_buffer)
|
|
||||||
rc = _assuan_error (ASSUAN_Out_Of_Core);
|
|
||||||
}
|
|
||||||
|
|
||||||
leave:
|
|
||||||
if (!nodataexpected)
|
|
||||||
free_membuf (&mb);
|
|
||||||
ctx->in_inquire = 0;
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
_assuan_inquire_release (assuan_context_t ctx)
|
|
||||||
{
|
|
||||||
if (ctx->in_inquire)
|
|
||||||
{
|
|
||||||
if (ctx->inquire_membuf)
|
|
||||||
{
|
|
||||||
free_membuf (ctx->inquire_membuf);
|
|
||||||
free (ctx->inquire_membuf);
|
|
||||||
}
|
|
||||||
ctx->in_inquire = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
_assuan_inquire_ext_cb (assuan_context_t ctx)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
unsigned char *line;
|
|
||||||
int linelen;
|
|
||||||
struct membuf *mb;
|
|
||||||
unsigned char *p;
|
|
||||||
|
|
||||||
line = (unsigned char *) ctx->inbound.line;
|
|
||||||
linelen = ctx->inbound.linelen;
|
|
||||||
mb = ctx->inquire_membuf;
|
|
||||||
|
|
||||||
if (line[0] == 'C' && line[1] == 'A' && line[2] == 'N')
|
|
||||||
{
|
|
||||||
rc = _assuan_error (ASSUAN_Canceled);
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
if (line[0] == 'E' && line[1] == 'N' && line[2] == 'D'
|
|
||||||
&& (!line[3] || line[3] == ' '))
|
|
||||||
{
|
|
||||||
rc = 0;
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (line[0] != 'D' || line[1] != ' ' || mb == NULL)
|
|
||||||
{
|
|
||||||
rc = _assuan_error (ASSUAN_Unexpected_Command);
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (linelen < 3)
|
|
||||||
return 0;
|
|
||||||
line += 2;
|
|
||||||
linelen -= 2;
|
|
||||||
|
|
||||||
p = line;
|
|
||||||
while (linelen)
|
|
||||||
{
|
|
||||||
for (;linelen && *p != '%'; linelen--, p++)
|
|
||||||
;
|
|
||||||
put_membuf (mb, line, p-line);
|
|
||||||
if (linelen > 2)
|
|
||||||
{ /* handle escaping */
|
|
||||||
unsigned char tmp[1];
|
|
||||||
p++;
|
|
||||||
*tmp = xtoi_2 (p);
|
|
||||||
p += 2;
|
|
||||||
linelen -= 3;
|
|
||||||
put_membuf (mb, tmp, 1);
|
|
||||||
}
|
|
||||||
line = p;
|
|
||||||
}
|
|
||||||
if (mb->too_large)
|
|
||||||
{
|
|
||||||
rc = _assuan_error (ASSUAN_Too_Much_Data);
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
leave:
|
|
||||||
{
|
|
||||||
size_t buf_len = 0;
|
|
||||||
unsigned char *buf = NULL;
|
|
||||||
|
|
||||||
if (mb)
|
|
||||||
{
|
|
||||||
buf = get_membuf (mb, &buf_len);
|
|
||||||
if (!buf)
|
|
||||||
rc = _assuan_error (ASSUAN_Out_Of_Core);
|
|
||||||
free_membuf (mb);
|
|
||||||
free (mb);
|
|
||||||
ctx->inquire_membuf = NULL;
|
|
||||||
}
|
|
||||||
ctx->in_inquire = 0;
|
|
||||||
rc = (ctx->inquire_cb) (ctx->inquire_cb_data, rc, buf, buf_len);
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* assuan_inquire_ext:
|
|
||||||
* @ctx: An assuan context
|
|
||||||
* @keyword: The keyword used for the inquire
|
|
||||||
* @maxlen: If not 0, the size limit of the inquired data.
|
|
||||||
* @cb: A callback handler which is invoked after the operation completed.
|
|
||||||
* @cb_data: A user-provided value passed to the callback handler.
|
|
||||||
*
|
|
||||||
* A Server may use this to Send an inquire. r_buffer, r_length and
|
|
||||||
* maxlen may all be NULL/0 to indicate that no real data is expected.
|
|
||||||
* When this function returns,
|
|
||||||
*
|
|
||||||
* Return value: 0 on success or an ASSUAN error code
|
|
||||||
**/
|
|
||||||
assuan_error_t
|
|
||||||
assuan_inquire_ext (assuan_context_t ctx, const char *keyword, size_t maxlen,
|
|
||||||
int (*cb) (void *cb_data, int rc, unsigned char *buf,
|
|
||||||
size_t len),
|
|
||||||
void *cb_data)
|
|
||||||
{
|
|
||||||
assuan_error_t rc;
|
|
||||||
struct membuf *mb = NULL;
|
|
||||||
char cmdbuf[LINELENGTH-10]; /* (10 = strlen ("INQUIRE ")+CR,LF) */
|
|
||||||
|
|
||||||
if (!ctx || !keyword || (10 + strlen (keyword) >= sizeof (cmdbuf)))
|
|
||||||
return _assuan_error (ASSUAN_Invalid_Value);
|
|
||||||
if (!ctx->is_server)
|
|
||||||
return _assuan_error (ASSUAN_Not_A_Server);
|
|
||||||
if (ctx->in_inquire)
|
|
||||||
return _assuan_error (ASSUAN_Nested_Commands);
|
|
||||||
|
|
||||||
mb = malloc (sizeof (struct membuf));
|
|
||||||
if (!mb)
|
|
||||||
return _assuan_error (ASSUAN_Out_Of_Core);
|
|
||||||
init_membuf (mb, maxlen ? maxlen : 1024, maxlen);
|
|
||||||
|
|
||||||
strcpy (stpcpy (cmdbuf, "INQUIRE "), keyword);
|
|
||||||
rc = assuan_write_line (ctx, cmdbuf);
|
|
||||||
if (rc)
|
|
||||||
{
|
|
||||||
free_membuf (mb);
|
|
||||||
free (mb);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->in_inquire = 1;
|
|
||||||
|
|
||||||
/* Set up the continuation. */
|
|
||||||
ctx->inquire_cb = cb;
|
|
||||||
ctx->inquire_cb_data = cb_data;
|
|
||||||
ctx->inquire_membuf = mb;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,245 +0,0 @@
|
|||||||
/* assuan-io.c - Wraps the read and write functions.
|
|
||||||
* Copyright (C) 2002, 2004, 2006, 2007, 2008 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include <config.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <time.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#ifdef HAVE_SYS_SOCKET_H
|
|
||||||
# include <sys/socket.h>
|
|
||||||
#endif
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#ifdef HAVE_W32_SYSTEM
|
|
||||||
# include <windows.h>
|
|
||||||
#else
|
|
||||||
# include <sys/wait.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "assuan-defs.h"
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef HAVE_W32_SYSTEM
|
|
||||||
pid_t
|
|
||||||
_assuan_waitpid (pid_t pid, int *status, int options)
|
|
||||||
{
|
|
||||||
return waitpid (pid, status, options);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
static ssize_t
|
|
||||||
do_io_read (assuan_fd_t fd, void *buffer, size_t size)
|
|
||||||
{
|
|
||||||
#if defined(HAVE_W32_SYSTEM) && !defined(_ASSUAN_IN_GPGME_BUILD_ASSUAN)
|
|
||||||
/* 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 n;
|
|
||||||
|
|
||||||
n = recv (HANDLE2SOCKET(fd), buffer, size, 0);
|
|
||||||
if (n == -1)
|
|
||||||
{
|
|
||||||
switch (WSAGetLastError ())
|
|
||||||
{
|
|
||||||
case WSAENOTSOCK:
|
|
||||||
{
|
|
||||||
DWORD nread = 0;
|
|
||||||
|
|
||||||
n = ReadFile (fd, buffer, size, &nread, NULL);
|
|
||||||
if (!n)
|
|
||||||
{
|
|
||||||
switch (GetLastError())
|
|
||||||
{
|
|
||||||
case ERROR_BROKEN_PIPE: errno = EPIPE; break;
|
|
||||||
default: errno = EIO;
|
|
||||||
}
|
|
||||||
n = -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
n = (int)nread;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WSAEWOULDBLOCK: errno = EAGAIN; break;
|
|
||||||
case ERROR_BROKEN_PIPE: errno = EPIPE; break;
|
|
||||||
default: errno = EIO; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
#else /*!HAVE_W32_SYSTEM*/
|
|
||||||
return read (fd, buffer, size);
|
|
||||||
#endif /*!HAVE_W32_SYSTEM*/
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ssize_t
|
|
||||||
_assuan_io_read (assuan_fd_t fd, void *buffer, size_t size)
|
|
||||||
{
|
|
||||||
ssize_t retval;
|
|
||||||
|
|
||||||
if (_assuan_io_hooks.read_hook
|
|
||||||
&& _assuan_io_hooks.read_hook (NULL, fd, buffer, size, &retval) == 1)
|
|
||||||
return retval;
|
|
||||||
|
|
||||||
return do_io_read (fd, buffer, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t
|
|
||||||
_assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size)
|
|
||||||
{
|
|
||||||
ssize_t retval;
|
|
||||||
|
|
||||||
if (_assuan_io_hooks.read_hook
|
|
||||||
&& _assuan_io_hooks.read_hook (ctx, ctx->inbound.fd,
|
|
||||||
buffer, size, &retval) == 1)
|
|
||||||
return retval;
|
|
||||||
|
|
||||||
return do_io_read (ctx->inbound.fd, buffer, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static ssize_t
|
|
||||||
do_io_write (assuan_fd_t fd, const void *buffer, size_t size)
|
|
||||||
{
|
|
||||||
#if defined(HAVE_W32_SYSTEM) && !defined(_ASSUAN_IN_GPGME_BUILD_ASSUAN)
|
|
||||||
/* 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 n;
|
|
||||||
|
|
||||||
n = send (HANDLE2SOCKET(fd), buffer, size, 0);
|
|
||||||
if (n == -1 && WSAGetLastError () == WSAENOTSOCK)
|
|
||||||
{
|
|
||||||
DWORD nwrite;
|
|
||||||
|
|
||||||
n = WriteFile (fd, buffer, size, &nwrite, NULL);
|
|
||||||
if (!n)
|
|
||||||
{
|
|
||||||
switch (GetLastError ())
|
|
||||||
{
|
|
||||||
case ERROR_BROKEN_PIPE:
|
|
||||||
case ERROR_NO_DATA: errno = EPIPE; break;
|
|
||||||
default: errno = EIO; break;
|
|
||||||
}
|
|
||||||
n = -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
n = (int)nwrite;
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
#else /*!HAVE_W32_SYSTEM*/
|
|
||||||
return write (fd, buffer, size);
|
|
||||||
#endif /*!HAVE_W32_SYSTEM*/
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t
|
|
||||||
_assuan_io_write (assuan_fd_t fd, const void *buffer, size_t size)
|
|
||||||
{
|
|
||||||
ssize_t retval;
|
|
||||||
|
|
||||||
if (_assuan_io_hooks.write_hook
|
|
||||||
&& _assuan_io_hooks.write_hook (NULL, fd, buffer, size, &retval) == 1)
|
|
||||||
return retval;
|
|
||||||
return do_io_write (fd, buffer, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t
|
|
||||||
_assuan_simple_write (assuan_context_t ctx, const void *buffer, size_t size)
|
|
||||||
{
|
|
||||||
ssize_t retval;
|
|
||||||
|
|
||||||
if (_assuan_io_hooks.write_hook
|
|
||||||
&& _assuan_io_hooks.write_hook (ctx, ctx->outbound.fd,
|
|
||||||
buffer, size, &retval) == 1)
|
|
||||||
return retval;
|
|
||||||
|
|
||||||
return do_io_write (ctx->outbound.fd, buffer, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_W32_SYSTEM
|
|
||||||
int
|
|
||||||
_assuan_simple_sendmsg (assuan_context_t ctx, void *msg)
|
|
||||||
#else
|
|
||||||
ssize_t
|
|
||||||
_assuan_simple_sendmsg (assuan_context_t ctx, struct msghdr *msg)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
#ifdef HAVE_W32_SYSTEM
|
|
||||||
return _assuan_error (ASSUAN_Not_Implemented);
|
|
||||||
#else
|
|
||||||
int ret;
|
|
||||||
while ( (ret = sendmsg (ctx->outbound.fd, msg, 0)) == -1 && errno == EINTR)
|
|
||||||
;
|
|
||||||
return ret;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_W32_SYSTEM
|
|
||||||
int
|
|
||||||
_assuan_simple_recvmsg (assuan_context_t ctx, void *msg)
|
|
||||||
#else
|
|
||||||
ssize_t
|
|
||||||
_assuan_simple_recvmsg (assuan_context_t ctx, struct msghdr *msg)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
#ifdef HAVE_W32_SYSTEM
|
|
||||||
return _assuan_error (ASSUAN_Not_Implemented);
|
|
||||||
#else
|
|
||||||
int ret;
|
|
||||||
while ( (ret = recvmsg (ctx->inbound.fd, msg, 0)) == -1 && errno == EINTR)
|
|
||||||
;
|
|
||||||
return ret;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
_assuan_usleep (unsigned int usec)
|
|
||||||
{
|
|
||||||
if (usec)
|
|
||||||
{
|
|
||||||
#ifdef HAVE_NANOSLEEP
|
|
||||||
struct timespec req;
|
|
||||||
struct timespec rem;
|
|
||||||
|
|
||||||
req.tv_sec = 0;
|
|
||||||
req.tv_nsec = usec * 1000;
|
|
||||||
|
|
||||||
while (nanosleep (&req, &rem) < 0 && errno == EINTR)
|
|
||||||
req = rem;
|
|
||||||
|
|
||||||
#elif defined(HAVE_W32_SYSTEM)
|
|
||||||
Sleep (usec / 1000);
|
|
||||||
#else
|
|
||||||
struct timeval tv;
|
|
||||||
|
|
||||||
tv.tv_sec = usec / 1000000;
|
|
||||||
tv.tv_usec = usec % 1000000;
|
|
||||||
select (0, NULL, NULL, NULL, &tv);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,155 +0,0 @@
|
|||||||
/* assuan-listen.c - Wait for a connection (server)
|
|
||||||
* Copyright (C) 2001, 2002, 2004 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include "assuan-defs.h"
|
|
||||||
|
|
||||||
assuan_error_t
|
|
||||||
assuan_set_hello_line (assuan_context_t ctx, const char *line)
|
|
||||||
{
|
|
||||||
if (!ctx)
|
|
||||||
return _assuan_error (ASSUAN_Invalid_Value);
|
|
||||||
if (!line)
|
|
||||||
{
|
|
||||||
xfree (ctx->hello_line);
|
|
||||||
ctx->hello_line = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char *buf = xtrymalloc (3+strlen(line)+1);
|
|
||||||
if (!buf)
|
|
||||||
return _assuan_error (ASSUAN_Out_Of_Core);
|
|
||||||
if (strchr (line, '\n'))
|
|
||||||
strcpy (buf, line);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
strcpy (buf, "OK ");
|
|
||||||
strcpy (buf+3, line);
|
|
||||||
}
|
|
||||||
xfree (ctx->hello_line);
|
|
||||||
ctx->hello_line = buf;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* assuan_accept:
|
|
||||||
* @ctx: context
|
|
||||||
*
|
|
||||||
* Cancel any existing connection and wait for a connection from a
|
|
||||||
* client. The initial handshake is performed which may include an
|
|
||||||
* initial authentication or encryption negotiation.
|
|
||||||
*
|
|
||||||
* Return value: 0 on success or an error if the connection could for
|
|
||||||
* some reason not be established.
|
|
||||||
**/
|
|
||||||
assuan_error_t
|
|
||||||
assuan_accept (assuan_context_t ctx)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
const char *p, *pend;
|
|
||||||
|
|
||||||
if (!ctx)
|
|
||||||
return _assuan_error (ASSUAN_Invalid_Value);
|
|
||||||
|
|
||||||
if (ctx->pipe_mode > 1)
|
|
||||||
return -1; /* second invocation for pipemode -> terminate */
|
|
||||||
ctx->finish_handler (ctx);
|
|
||||||
|
|
||||||
rc = ctx->accept_handler (ctx);
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
/* Send the hello. */
|
|
||||||
p = ctx->hello_line;
|
|
||||||
if (p && (pend = strchr (p, '\n')))
|
|
||||||
{ /* This is a multi line hello. Send all but the last line as
|
|
||||||
comments. */
|
|
||||||
do
|
|
||||||
{
|
|
||||||
rc = _assuan_write_line (ctx, "# ", p, pend - p);
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
p = pend + 1;
|
|
||||||
pend = strchr (p, '\n');
|
|
||||||
}
|
|
||||||
while (pend);
|
|
||||||
rc = _assuan_write_line (ctx, "OK ", p, strlen (p));
|
|
||||||
}
|
|
||||||
else if (p)
|
|
||||||
rc = assuan_write_line (ctx, p);
|
|
||||||
else
|
|
||||||
rc = assuan_write_line (ctx, "OK Pleased to meet you");
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
if (ctx->pipe_mode)
|
|
||||||
ctx->pipe_mode = 2;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
assuan_fd_t
|
|
||||||
assuan_get_input_fd (assuan_context_t ctx)
|
|
||||||
{
|
|
||||||
return ctx? ctx->input_fd : ASSUAN_INVALID_FD;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
assuan_fd_t
|
|
||||||
assuan_get_output_fd (assuan_context_t ctx)
|
|
||||||
{
|
|
||||||
return ctx? ctx->output_fd : ASSUAN_INVALID_FD;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Close the fd descriptor set by the command INPUT FD=n. We handle
|
|
||||||
this fd inside assuan so that we can do some initial checks */
|
|
||||||
assuan_error_t
|
|
||||||
assuan_close_input_fd (assuan_context_t ctx)
|
|
||||||
{
|
|
||||||
if (!ctx || ctx->input_fd == ASSUAN_INVALID_FD)
|
|
||||||
return _assuan_error (ASSUAN_Invalid_Value);
|
|
||||||
_assuan_close (ctx->input_fd);
|
|
||||||
ctx->input_fd = ASSUAN_INVALID_FD;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Close the fd descriptor set by the command OUTPUT FD=n. We handle
|
|
||||||
this fd inside assuan so that we can do some initial checks */
|
|
||||||
assuan_error_t
|
|
||||||
assuan_close_output_fd (assuan_context_t ctx)
|
|
||||||
{
|
|
||||||
if (!ctx || ctx->output_fd == ASSUAN_INVALID_FD)
|
|
||||||
return _assuan_error (ASSUAN_Invalid_Value);
|
|
||||||
|
|
||||||
_assuan_close (ctx->output_fd);
|
|
||||||
ctx->output_fd = ASSUAN_INVALID_FD;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,291 +0,0 @@
|
|||||||
/* assuan-logging.c - Default logging function.
|
|
||||||
* Copyright (C) 2002, 2003, 2004, 2007 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include <config.h>
|
|
||||||
#endif
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#ifdef HAVE_W32_SYSTEM
|
|
||||||
#include <windows.h>
|
|
||||||
#endif /*HAVE_W32_SYSTEM*/
|
|
||||||
#include <errno.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
#include "assuan-defs.h"
|
|
||||||
|
|
||||||
static char prefix_buffer[80];
|
|
||||||
static FILE *_assuan_log;
|
|
||||||
static int full_logging;
|
|
||||||
|
|
||||||
void
|
|
||||||
_assuan_set_default_log_stream (FILE *fp)
|
|
||||||
{
|
|
||||||
if (!_assuan_log)
|
|
||||||
{
|
|
||||||
_assuan_log = fp;
|
|
||||||
full_logging = !!getenv ("ASSUAN_FULL_LOGGING");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
assuan_set_assuan_log_stream (FILE *fp)
|
|
||||||
{
|
|
||||||
_assuan_log = fp;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Set the per context log stream. Also enable the default log stream
|
|
||||||
if it has not been set. */
|
|
||||||
void
|
|
||||||
assuan_set_log_stream (assuan_context_t ctx, FILE *fp)
|
|
||||||
{
|
|
||||||
if (ctx)
|
|
||||||
{
|
|
||||||
if (ctx->log_fp)
|
|
||||||
fflush (ctx->log_fp);
|
|
||||||
ctx->log_fp = fp;
|
|
||||||
_assuan_set_default_log_stream (fp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
FILE *
|
|
||||||
assuan_get_assuan_log_stream (void)
|
|
||||||
{
|
|
||||||
return _assuan_log ? _assuan_log : stderr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Set the prefix to be used for logging to TEXT or
|
|
||||||
resets it to the default if TEXT is NULL. */
|
|
||||||
void
|
|
||||||
assuan_set_assuan_log_prefix (const char *text)
|
|
||||||
{
|
|
||||||
if (text)
|
|
||||||
{
|
|
||||||
strncpy (prefix_buffer, text, sizeof (prefix_buffer)-1);
|
|
||||||
prefix_buffer[sizeof (prefix_buffer)-1] = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
*prefix_buffer = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *
|
|
||||||
assuan_get_assuan_log_prefix (void)
|
|
||||||
{
|
|
||||||
return prefix_buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
_assuan_log_printf (const char *format, ...)
|
|
||||||
{
|
|
||||||
va_list arg_ptr;
|
|
||||||
FILE *fp;
|
|
||||||
const char *prf;
|
|
||||||
int save_errno = errno;
|
|
||||||
|
|
||||||
fp = assuan_get_assuan_log_stream ();
|
|
||||||
prf = assuan_get_assuan_log_prefix ();
|
|
||||||
if (*prf)
|
|
||||||
fprintf (fp, "%s[%u]: ", prf, (unsigned int)getpid ());
|
|
||||||
|
|
||||||
va_start (arg_ptr, format);
|
|
||||||
vfprintf (fp, format, arg_ptr );
|
|
||||||
va_end (arg_ptr);
|
|
||||||
/* If the log stream is a file, the output would be buffered. This
|
|
||||||
is bad for debugging, thus we flush the stream if FORMAT ends
|
|
||||||
with a LF. */
|
|
||||||
if (format && *format && format[strlen(format)-1] == '\n')
|
|
||||||
fflush (fp);
|
|
||||||
errno = save_errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Dump a possibly binary string (used for debugging). Distinguish
|
|
||||||
ascii text from binary and print it accordingly. This function
|
|
||||||
takes FILE pointer arg because logging may be enabled on a per
|
|
||||||
context basis. */
|
|
||||||
void
|
|
||||||
_assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length)
|
|
||||||
{
|
|
||||||
const unsigned char *s;
|
|
||||||
unsigned int n;
|
|
||||||
|
|
||||||
for (n = length, s = buffer; n; n--, s++)
|
|
||||||
if ((! isascii (*s) || iscntrl (*s) || ! isprint (*s)) && !(*s >= 0x80))
|
|
||||||
break;
|
|
||||||
|
|
||||||
s = buffer;
|
|
||||||
if (! n && *s != '[')
|
|
||||||
fwrite (buffer, length, 1, fp);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#ifdef HAVE_FLOCKFILE
|
|
||||||
flockfile (fp);
|
|
||||||
#endif
|
|
||||||
putc_unlocked ('[', fp);
|
|
||||||
if (length > 16 && ! full_logging)
|
|
||||||
{
|
|
||||||
for (n = 0; n < 12; n++, s++)
|
|
||||||
fprintf (fp, " %02x", *s);
|
|
||||||
fprintf (fp, " ...(%d bytes skipped)", (int) length - 12);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (n = 0; n < length; n++, s++)
|
|
||||||
fprintf (fp, " %02x", *s);
|
|
||||||
}
|
|
||||||
putc_unlocked (' ', fp);
|
|
||||||
putc_unlocked (']', fp);
|
|
||||||
#ifdef HAVE_FUNLOCKFILE
|
|
||||||
funlockfile (fp);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Log a user supplied string. Escapes non-printable before
|
|
||||||
printing. */
|
|
||||||
void
|
|
||||||
_assuan_log_sanitized_string (const char *string)
|
|
||||||
{
|
|
||||||
const unsigned char *s = (const unsigned char *) string;
|
|
||||||
FILE *fp = assuan_get_assuan_log_stream ();
|
|
||||||
|
|
||||||
if (! *s)
|
|
||||||
return;
|
|
||||||
|
|
||||||
#ifdef HAVE_FLOCKFILE
|
|
||||||
flockfile (fp);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (; *s; s++)
|
|
||||||
{
|
|
||||||
int c = 0;
|
|
||||||
|
|
||||||
switch (*s)
|
|
||||||
{
|
|
||||||
case '\r':
|
|
||||||
c = 'r';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '\n':
|
|
||||||
c = 'n';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '\f':
|
|
||||||
c = 'f';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '\v':
|
|
||||||
c = 'v';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '\b':
|
|
||||||
c = 'b';
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
if ((isascii (*s) && isprint (*s)) || (*s >= 0x80))
|
|
||||||
putc_unlocked (*s, fp);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
putc_unlocked ('\\', fp);
|
|
||||||
fprintf (fp, "x%02x", *s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c)
|
|
||||||
{
|
|
||||||
putc_unlocked ('\\', fp);
|
|
||||||
putc_unlocked (c, fp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_FUNLOCKFILE
|
|
||||||
funlockfile (fp);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_W32_SYSTEM
|
|
||||||
const char *
|
|
||||||
_assuan_w32_strerror (int ec)
|
|
||||||
{
|
|
||||||
static char strerr[256];
|
|
||||||
|
|
||||||
if (ec == -1)
|
|
||||||
ec = (int)GetLastError ();
|
|
||||||
FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, ec,
|
|
||||||
MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
||||||
strerr, sizeof (strerr)-1, NULL);
|
|
||||||
return strerr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int (*my_strerror_r) (unsigned int err, char *buf, size_t buflen);
|
|
||||||
static const char * (*my_strsource) (unsigned int err);
|
|
||||||
|
|
||||||
static int
|
|
||||||
load_libgpg_error (void)
|
|
||||||
{
|
|
||||||
/* This code is not race free but suitable for our purpose. */
|
|
||||||
static volatile int initialized;
|
|
||||||
void *handle;
|
|
||||||
|
|
||||||
if (initialized)
|
|
||||||
return (my_strerror_r && my_strsource)? 0:-1;
|
|
||||||
handle = LoadLibrary ("libgpg-error-0.dll");
|
|
||||||
if (handle)
|
|
||||||
{
|
|
||||||
void *foo, *bar;
|
|
||||||
foo = GetProcAddress (handle, "gpg_strerror_r");
|
|
||||||
bar = GetProcAddress (handle, "gpg_strsource");
|
|
||||||
if (foo && bar)
|
|
||||||
{
|
|
||||||
my_strerror_r = foo;
|
|
||||||
my_strsource = bar;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
CloseHandle (handle);
|
|
||||||
}
|
|
||||||
initialized = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
_assuan_gpg_strerror_r (unsigned int err, char *buf, size_t buflen)
|
|
||||||
{
|
|
||||||
if (load_libgpg_error ())
|
|
||||||
return -1;
|
|
||||||
return my_strerror_r (err, buf, buflen);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const char *
|
|
||||||
_assuan_gpg_strsource (unsigned int err)
|
|
||||||
{
|
|
||||||
if (load_libgpg_error ())
|
|
||||||
return NULL;
|
|
||||||
return my_strsource (err);
|
|
||||||
}
|
|
||||||
#endif /*HAVE_W32_SYSTEM*/
|
|
File diff suppressed because it is too large
Load Diff
@ -1,189 +0,0 @@
|
|||||||
/* assuan-pipe-server.c - Assuan server working over a pipe
|
|
||||||
* Copyright (C) 2001, 2002 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#ifdef HAVE_W32_SYSTEM
|
|
||||||
#include <windows.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "assuan-defs.h"
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
deinit_pipe_server (assuan_context_t ctx)
|
|
||||||
{
|
|
||||||
/* nothing to do for this simple server */
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
accept_connection (assuan_context_t ctx)
|
|
||||||
{
|
|
||||||
/* This is a NOP for a pipe server */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
finish_connection (assuan_context_t ctx)
|
|
||||||
{
|
|
||||||
/* This is a NOP for a pipe server */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create a new context. Note that the handlers are set up for a pipe
|
|
||||||
server/client - this way we don't need extra dummy functions */
|
|
||||||
int
|
|
||||||
_assuan_new_context (assuan_context_t *r_ctx)
|
|
||||||
{
|
|
||||||
static struct assuan_io io = { _assuan_simple_read,
|
|
||||||
_assuan_simple_write,
|
|
||||||
0, 0 };
|
|
||||||
|
|
||||||
assuan_context_t ctx;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
*r_ctx = NULL;
|
|
||||||
ctx = xtrycalloc (1, sizeof *ctx);
|
|
||||||
if (!ctx)
|
|
||||||
return _assuan_error (ASSUAN_Out_Of_Core);
|
|
||||||
ctx->input_fd = ASSUAN_INVALID_FD;
|
|
||||||
ctx->output_fd = ASSUAN_INVALID_FD;
|
|
||||||
|
|
||||||
ctx->inbound.fd = ASSUAN_INVALID_FD;
|
|
||||||
ctx->outbound.fd = ASSUAN_INVALID_FD;
|
|
||||||
ctx->io = &io;
|
|
||||||
|
|
||||||
ctx->listen_fd = ASSUAN_INVALID_FD;
|
|
||||||
/* Use the pipe server handler as a default. */
|
|
||||||
ctx->deinit_handler = deinit_pipe_server;
|
|
||||||
ctx->accept_handler = accept_connection;
|
|
||||||
ctx->finish_handler = finish_connection;
|
|
||||||
|
|
||||||
rc = _assuan_register_std_commands (ctx);
|
|
||||||
if (rc)
|
|
||||||
xfree (ctx);
|
|
||||||
else
|
|
||||||
*r_ctx = ctx;
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Returns true if atoi(S) denotes a valid socket. */
|
|
||||||
#ifndef HAVE_W32_SYSTEM
|
|
||||||
static int
|
|
||||||
is_valid_socket (const char *s)
|
|
||||||
{
|
|
||||||
struct stat buf;
|
|
||||||
|
|
||||||
if ( fstat (atoi (s), &buf ) )
|
|
||||||
return 0;
|
|
||||||
return S_ISSOCK (buf.st_mode);
|
|
||||||
}
|
|
||||||
#endif /*!HAVE_W32_SYSTEM*/
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
assuan_init_pipe_server (assuan_context_t *r_ctx, int filedes[2])
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
rc = _assuan_new_context (r_ctx);
|
|
||||||
if (!rc)
|
|
||||||
{
|
|
||||||
assuan_context_t ctx = *r_ctx;
|
|
||||||
const char *s;
|
|
||||||
unsigned long ul;
|
|
||||||
|
|
||||||
ctx->is_server = 1;
|
|
||||||
#ifdef HAVE_W32_SYSTEM
|
|
||||||
/* MS Windows has so many different types of handle that one
|
|
||||||
needs to tranlsate them at many place forth and back. Also
|
|
||||||
make sure that the file descriptors are in binary mode. */
|
|
||||||
setmode (filedes[0], O_BINARY);
|
|
||||||
setmode (filedes[1], O_BINARY);
|
|
||||||
ctx->inbound.fd = (void*)_get_osfhandle (filedes[0]);
|
|
||||||
ctx->outbound.fd = (void*)_get_osfhandle (filedes[1]);
|
|
||||||
#else
|
|
||||||
s = getenv ("_assuan_connection_fd");
|
|
||||||
if (s && *s && is_valid_socket (s) )
|
|
||||||
{
|
|
||||||
/* Well, we are called with an bi-directional file
|
|
||||||
descriptor. Prepare for using sendmsg/recvmsg. In this
|
|
||||||
case we ignore the passed file descriptors. */
|
|
||||||
ctx->inbound.fd = ctx->outbound.fd = atoi (s);
|
|
||||||
_assuan_init_uds_io (ctx);
|
|
||||||
ctx->deinit_handler = _assuan_uds_deinit;
|
|
||||||
}
|
|
||||||
else if (filedes && filedes[0] != ASSUAN_INVALID_FD
|
|
||||||
&& filedes[1] != ASSUAN_INVALID_FD )
|
|
||||||
{
|
|
||||||
/* Standard pipe server. */
|
|
||||||
ctx->inbound.fd = filedes[0];
|
|
||||||
ctx->outbound.fd = filedes[1];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_assuan_release_context (*r_ctx);
|
|
||||||
*r_ctx = NULL;
|
|
||||||
return ASSUAN_Problem_Starting_Server;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
ctx->pipe_mode = 1;
|
|
||||||
|
|
||||||
s = getenv ("_assuan_pipe_connect_pid");
|
|
||||||
if (s && (ul=strtoul (s, NULL, 10)) && ul)
|
|
||||||
ctx->pid = (pid_t)ul;
|
|
||||||
else
|
|
||||||
ctx->pid = (pid_t)-1;
|
|
||||||
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
_assuan_release_context (assuan_context_t ctx)
|
|
||||||
{
|
|
||||||
if (ctx)
|
|
||||||
{
|
|
||||||
_assuan_inquire_release (ctx);
|
|
||||||
xfree (ctx->hello_line);
|
|
||||||
xfree (ctx->okay_line);
|
|
||||||
xfree (ctx->cmdtbl);
|
|
||||||
xfree (ctx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
assuan_deinit_server (assuan_context_t ctx)
|
|
||||||
{
|
|
||||||
if (ctx)
|
|
||||||
{
|
|
||||||
/* We use this function pointer to avoid linking other server
|
|
||||||
when not needed but still allow for a generic deinit function. */
|
|
||||||
ctx->deinit_handler (ctx);
|
|
||||||
ctx->deinit_handler = NULL;
|
|
||||||
_assuan_release_context (ctx);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,180 +0,0 @@
|
|||||||
/* assuan-socket-connect.c - Assuan socket based client
|
|
||||||
* Copyright (C) 2002, 2003, 2004 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#ifndef HAVE_W32_SYSTEM
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/un.h>
|
|
||||||
#else
|
|
||||||
#include <windows.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "assuan-defs.h"
|
|
||||||
|
|
||||||
/* Hacks for Slowaris. */
|
|
||||||
#ifndef PF_LOCAL
|
|
||||||
# ifdef PF_UNIX
|
|
||||||
# define PF_LOCAL PF_UNIX
|
|
||||||
# else
|
|
||||||
# define PF_LOCAL AF_UNIX
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
#ifndef AF_LOCAL
|
|
||||||
# define AF_LOCAL AF_UNIX
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef SUN_LEN
|
|
||||||
# define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) \
|
|
||||||
+ strlen ((ptr)->sun_path))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
do_finish (assuan_context_t ctx)
|
|
||||||
{
|
|
||||||
if (ctx->inbound.fd != ASSUAN_INVALID_FD)
|
|
||||||
{
|
|
||||||
_assuan_close (ctx->inbound.fd);
|
|
||||||
}
|
|
||||||
ctx->inbound.fd = ASSUAN_INVALID_FD;
|
|
||||||
ctx->outbound.fd = ASSUAN_INVALID_FD;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
do_deinit (assuan_context_t ctx)
|
|
||||||
{
|
|
||||||
do_finish (ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Make a connection to the Unix domain socket NAME and return a new
|
|
||||||
Assuan context in CTX. SERVER_PID is currently not used but may
|
|
||||||
become handy in the future. */
|
|
||||||
assuan_error_t
|
|
||||||
assuan_socket_connect (assuan_context_t *r_ctx,
|
|
||||||
const char *name, pid_t server_pid)
|
|
||||||
{
|
|
||||||
return assuan_socket_connect_ext (r_ctx, name, server_pid, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Make a connection to the Unix domain socket NAME and return a new
|
|
||||||
Assuan context in CTX. SERVER_PID is currently not used but may
|
|
||||||
become handy in the future. With flags set to 1 sendmsg and
|
|
||||||
recvmsg are used. */
|
|
||||||
assuan_error_t
|
|
||||||
assuan_socket_connect_ext (assuan_context_t *r_ctx,
|
|
||||||
const char *name, pid_t server_pid,
|
|
||||||
unsigned int flags)
|
|
||||||
{
|
|
||||||
static struct assuan_io io = { _assuan_simple_read, _assuan_simple_write,
|
|
||||||
NULL, NULL };
|
|
||||||
assuan_error_t err;
|
|
||||||
assuan_context_t ctx;
|
|
||||||
assuan_fd_t fd;
|
|
||||||
struct sockaddr_un srvr_addr;
|
|
||||||
size_t len;
|
|
||||||
const char *s;
|
|
||||||
|
|
||||||
if (!r_ctx || !name)
|
|
||||||
return _assuan_error (ASSUAN_Invalid_Value);
|
|
||||||
*r_ctx = NULL;
|
|
||||||
|
|
||||||
/* We require that the name starts with a slash, so that we
|
|
||||||
eventually can reuse this function for other socket types. To
|
|
||||||
make things easier we allow an optional driver prefix. */
|
|
||||||
s = name;
|
|
||||||
if (*s && s[1] == ':')
|
|
||||||
s += 2;
|
|
||||||
if (*s != DIRSEP_C && *s != '/')
|
|
||||||
return _assuan_error (ASSUAN_Invalid_Value);
|
|
||||||
|
|
||||||
if (strlen (name)+1 >= sizeof srvr_addr.sun_path)
|
|
||||||
return _assuan_error (ASSUAN_Invalid_Value);
|
|
||||||
|
|
||||||
err = _assuan_new_context (&ctx);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
ctx->deinit_handler = ((flags&1))? _assuan_uds_deinit : do_deinit;
|
|
||||||
ctx->finish_handler = do_finish;
|
|
||||||
|
|
||||||
fd = _assuan_sock_new (PF_LOCAL, SOCK_STREAM, 0);
|
|
||||||
if (fd == ASSUAN_INVALID_FD)
|
|
||||||
{
|
|
||||||
_assuan_log_printf ("can't create socket: %s\n", strerror (errno));
|
|
||||||
_assuan_release_context (ctx);
|
|
||||||
return _assuan_error (ASSUAN_General_Error);
|
|
||||||
}
|
|
||||||
|
|
||||||
memset (&srvr_addr, 0, sizeof srvr_addr);
|
|
||||||
srvr_addr.sun_family = AF_LOCAL;
|
|
||||||
strncpy (srvr_addr.sun_path, name, sizeof (srvr_addr.sun_path) - 1);
|
|
||||||
srvr_addr.sun_path[sizeof (srvr_addr.sun_path) - 1] = 0;
|
|
||||||
len = SUN_LEN (&srvr_addr);
|
|
||||||
|
|
||||||
if ( _assuan_sock_connect (fd, (struct sockaddr *) &srvr_addr, len) == -1 )
|
|
||||||
{
|
|
||||||
_assuan_log_printf ("can't connect to `%s': %s\n",
|
|
||||||
name, strerror (errno));
|
|
||||||
_assuan_release_context (ctx);
|
|
||||||
_assuan_close (fd);
|
|
||||||
return _assuan_error (ASSUAN_Connect_Failed);
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->inbound.fd = fd;
|
|
||||||
ctx->outbound.fd = fd;
|
|
||||||
ctx->io = &io;
|
|
||||||
if ((flags&1))
|
|
||||||
_assuan_init_uds_io (ctx);
|
|
||||||
|
|
||||||
/* initial handshake */
|
|
||||||
{
|
|
||||||
int okay, off;
|
|
||||||
|
|
||||||
err = _assuan_read_from_server (ctx, &okay, &off);
|
|
||||||
if (err)
|
|
||||||
_assuan_log_printf ("can't connect to server: %s\n",
|
|
||||||
assuan_strerror (err));
|
|
||||||
else if (okay != 1)
|
|
||||||
{
|
|
||||||
/*LOG ("can't connect to server: `");*/
|
|
||||||
_assuan_log_sanitized_string (ctx->inbound.line);
|
|
||||||
fprintf (assuan_get_assuan_log_stream (), "'\n");
|
|
||||||
err = _assuan_error (ASSUAN_Connect_Failed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
assuan_disconnect (ctx);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
*r_ctx = ctx;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,208 +0,0 @@
|
|||||||
/* assuan-socket-server.c - Assuan socket based server
|
|
||||||
* Copyright (C) 2002, 2007 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#ifdef HAVE_W32_SYSTEM
|
|
||||||
# include <windows.h>
|
|
||||||
# if HAVE_SYS_SOCKET_H
|
|
||||||
# include <sys/socket.h>
|
|
||||||
# elif HAVE_WS2TCPIP_H
|
|
||||||
# include <ws2tcpip.h>
|
|
||||||
# endif
|
|
||||||
#else
|
|
||||||
# include <sys/socket.h>
|
|
||||||
# include <sys/un.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#include "assuan-defs.h"
|
|
||||||
|
|
||||||
static struct assuan_io io = { _assuan_simple_read, _assuan_simple_write,
|
|
||||||
NULL, NULL };
|
|
||||||
|
|
||||||
static int
|
|
||||||
accept_connection_bottom (assuan_context_t ctx)
|
|
||||||
{
|
|
||||||
assuan_fd_t fd = ctx->connected_fd;
|
|
||||||
|
|
||||||
ctx->peercred.valid = 0;
|
|
||||||
#ifdef HAVE_SO_PEERCRED
|
|
||||||
{
|
|
||||||
struct ucred cr;
|
|
||||||
socklen_t cl = sizeof cr;
|
|
||||||
|
|
||||||
if ( !getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &cr, &cl))
|
|
||||||
{
|
|
||||||
ctx->peercred.pid = cr.pid;
|
|
||||||
ctx->peercred.uid = cr.uid;
|
|
||||||
ctx->peercred.gid = cr.gid;
|
|
||||||
ctx->peercred.valid = 1;
|
|
||||||
|
|
||||||
/* This overrides any already set PID if the function returns
|
|
||||||
a valid one. */
|
|
||||||
if (cr.pid != (pid_t)-1 && cr.pid)
|
|
||||||
ctx->pid = cr.pid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ctx->inbound.fd = fd;
|
|
||||||
ctx->inbound.eof = 0;
|
|
||||||
ctx->inbound.linelen = 0;
|
|
||||||
ctx->inbound.attic.linelen = 0;
|
|
||||||
ctx->inbound.attic.pending = 0;
|
|
||||||
|
|
||||||
ctx->outbound.fd = fd;
|
|
||||||
ctx->outbound.data.linelen = 0;
|
|
||||||
ctx->outbound.data.error = 0;
|
|
||||||
|
|
||||||
ctx->confidential = 0;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
accept_connection (assuan_context_t ctx)
|
|
||||||
{
|
|
||||||
assuan_fd_t fd;
|
|
||||||
struct sockaddr_un clnt_addr;
|
|
||||||
socklen_t len = sizeof clnt_addr;
|
|
||||||
|
|
||||||
fd = SOCKET2HANDLE(accept (HANDLE2SOCKET(ctx->listen_fd),
|
|
||||||
(struct sockaddr*)&clnt_addr, &len ));
|
|
||||||
if (fd == ASSUAN_INVALID_FD)
|
|
||||||
{
|
|
||||||
ctx->os_errno = errno;
|
|
||||||
return _assuan_error (ASSUAN_Accept_Failed);
|
|
||||||
}
|
|
||||||
if (_assuan_sock_check_nonce (fd, &ctx->listen_nonce))
|
|
||||||
{
|
|
||||||
_assuan_close (fd);
|
|
||||||
ctx->os_errno = EACCES;
|
|
||||||
return _assuan_error (ASSUAN_Accept_Failed);
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->connected_fd = fd;
|
|
||||||
return accept_connection_bottom (ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
finish_connection (assuan_context_t ctx)
|
|
||||||
{
|
|
||||||
if (ctx->inbound.fd != ASSUAN_INVALID_FD)
|
|
||||||
{
|
|
||||||
_assuan_close (ctx->inbound.fd);
|
|
||||||
}
|
|
||||||
ctx->inbound.fd = ASSUAN_INVALID_FD;
|
|
||||||
ctx->outbound.fd = ASSUAN_INVALID_FD;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
deinit_socket_server (assuan_context_t ctx)
|
|
||||||
{
|
|
||||||
finish_connection (ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize a server for the socket LISTEN_FD which has already be
|
|
||||||
put into listen mode */
|
|
||||||
int
|
|
||||||
assuan_init_socket_server (assuan_context_t *r_ctx, assuan_fd_t listen_fd)
|
|
||||||
{
|
|
||||||
return assuan_init_socket_server_ext (r_ctx, listen_fd, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize a server using the already accepted socket FD. This
|
|
||||||
function is deprecated. */
|
|
||||||
int
|
|
||||||
assuan_init_connected_socket_server (assuan_context_t *r_ctx, assuan_fd_t fd)
|
|
||||||
{
|
|
||||||
return assuan_init_socket_server_ext (r_ctx, fd, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Flag bits: 0 - use sendmsg/recvmsg to allow descriptor passing
|
|
||||||
1 - FD has already been accepted.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
assuan_init_socket_server_ext (assuan_context_t *r_ctx, assuan_fd_t fd,
|
|
||||||
unsigned int flags)
|
|
||||||
{
|
|
||||||
assuan_context_t ctx;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
*r_ctx = NULL;
|
|
||||||
ctx = xtrycalloc (1, sizeof *ctx);
|
|
||||||
if (!ctx)
|
|
||||||
return _assuan_error (ASSUAN_Out_Of_Core);
|
|
||||||
ctx->is_server = 1;
|
|
||||||
if ((flags & 2))
|
|
||||||
ctx->pipe_mode = 1; /* We want a second accept to indicate EOF. */
|
|
||||||
ctx->input_fd = ASSUAN_INVALID_FD;
|
|
||||||
ctx->output_fd = ASSUAN_INVALID_FD;
|
|
||||||
|
|
||||||
ctx->inbound.fd = ASSUAN_INVALID_FD;
|
|
||||||
ctx->outbound.fd = ASSUAN_INVALID_FD;
|
|
||||||
|
|
||||||
if ((flags & 2))
|
|
||||||
{
|
|
||||||
ctx->listen_fd = ASSUAN_INVALID_FD;
|
|
||||||
ctx->connected_fd = fd;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ctx->listen_fd = fd;
|
|
||||||
ctx->connected_fd = ASSUAN_INVALID_FD;
|
|
||||||
}
|
|
||||||
ctx->deinit_handler = (flags & 1)? _assuan_uds_deinit:deinit_socket_server;
|
|
||||||
ctx->accept_handler = ((flags & 2)
|
|
||||||
? accept_connection_bottom
|
|
||||||
: accept_connection);
|
|
||||||
ctx->finish_handler = finish_connection;
|
|
||||||
|
|
||||||
ctx->io = &io;
|
|
||||||
if ((flags & 1))
|
|
||||||
_assuan_init_uds_io (ctx);
|
|
||||||
|
|
||||||
rc = _assuan_register_std_commands (ctx);
|
|
||||||
if (rc)
|
|
||||||
xfree (ctx);
|
|
||||||
else
|
|
||||||
*r_ctx = ctx;
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Save a copy of NONCE in context CTX. This should be used to
|
|
||||||
register the server's nonce with an context established by
|
|
||||||
assuan_init_socket_server. */
|
|
||||||
void
|
|
||||||
assuan_set_sock_nonce (assuan_context_t ctx, assuan_sock_nonce_t *nonce)
|
|
||||||
{
|
|
||||||
if (ctx && nonce)
|
|
||||||
ctx->listen_nonce = *nonce;
|
|
||||||
}
|
|
@ -1,470 +0,0 @@
|
|||||||
/* assuan-socket.c
|
|
||||||
* Copyright (C) 2004, 2005 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#ifdef HAVE_W32_SYSTEM
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
|
||||||
#include <windows.h>
|
|
||||||
#include <wincrypt.h>
|
|
||||||
#include <io.h>
|
|
||||||
#else
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#endif
|
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "assuan-defs.h"
|
|
||||||
|
|
||||||
/* Hacks for Slowaris. */
|
|
||||||
#ifndef PF_LOCAL
|
|
||||||
# ifdef PF_UNIX
|
|
||||||
# define PF_LOCAL PF_UNIX
|
|
||||||
# else
|
|
||||||
# define PF_LOCAL AF_UNIX
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
#ifndef AF_LOCAL
|
|
||||||
# define AF_LOCAL AF_UNIX
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_W32_SYSTEM
|
|
||||||
#ifndef S_IRGRP
|
|
||||||
# define S_IRGRP 0
|
|
||||||
# define S_IWGRP 0
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_W32_SYSTEM
|
|
||||||
int
|
|
||||||
_assuan_sock_wsa2errno (int err)
|
|
||||||
{
|
|
||||||
switch (err)
|
|
||||||
{
|
|
||||||
case WSAENOTSOCK:
|
|
||||||
return EINVAL;
|
|
||||||
case WSAEWOULDBLOCK:
|
|
||||||
return EAGAIN;
|
|
||||||
case ERROR_BROKEN_PIPE:
|
|
||||||
return EPIPE;
|
|
||||||
case WSANOTINITIALISED:
|
|
||||||
return ENOSYS;
|
|
||||||
default:
|
|
||||||
return EIO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* W32: Fill BUFFER with LENGTH bytes of random. Returns -1 on
|
|
||||||
failure, 0 on success. Sets errno on failure. */
|
|
||||||
static int
|
|
||||||
get_nonce (char *buffer, size_t nbytes)
|
|
||||||
{
|
|
||||||
HCRYPTPROV prov;
|
|
||||||
int ret = -1;
|
|
||||||
|
|
||||||
if (!CryptAcquireContext (&prov, NULL, NULL, PROV_RSA_FULL,
|
|
||||||
(CRYPT_VERIFYCONTEXT|CRYPT_SILENT)) )
|
|
||||||
errno = ENODEV;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!CryptGenRandom (prov, nbytes, buffer))
|
|
||||||
errno = ENODEV;
|
|
||||||
else
|
|
||||||
ret = 0;
|
|
||||||
CryptReleaseContext (prov, 0);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* W32: The buffer for NONCE needs to be at least 16 bytes. Returns 0 on
|
|
||||||
success and sets errno on failure. */
|
|
||||||
static int
|
|
||||||
read_port_and_nonce (const char *fname, unsigned short *port, char *nonce)
|
|
||||||
{
|
|
||||||
FILE *fp;
|
|
||||||
char buffer[50], *p;
|
|
||||||
size_t nread;
|
|
||||||
int aval;
|
|
||||||
|
|
||||||
fp = fopen (fname, "rb");
|
|
||||||
if (!fp)
|
|
||||||
return -1;
|
|
||||||
nread = fread (buffer, 1, sizeof buffer - 1, fp);
|
|
||||||
fclose (fp);
|
|
||||||
if (!nread)
|
|
||||||
{
|
|
||||||
errno = ENOFILE;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
buffer[nread] = 0;
|
|
||||||
aval = atoi (buffer);
|
|
||||||
if (aval < 1 || aval > 65535)
|
|
||||||
{
|
|
||||||
errno = EINVAL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*port = (unsigned int)aval;
|
|
||||||
for (p=buffer; nread && *p != '\n'; p++, nread--)
|
|
||||||
;
|
|
||||||
if (*p != '\n' || nread != 17)
|
|
||||||
{
|
|
||||||
errno = EINVAL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
p++; nread--;
|
|
||||||
memcpy (nonce, p, 16);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif /*HAVE_W32_SYSTEM*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
_assuan_close (assuan_fd_t fd)
|
|
||||||
{
|
|
||||||
#ifdef _ASSUAN_CUSTOM_IO
|
|
||||||
return _assuan_custom_close (fd);
|
|
||||||
#else
|
|
||||||
#ifdef (HAVE_W32_SYSTEM)
|
|
||||||
int rc = closesocket (HANDLE2SOCKET(fd));
|
|
||||||
if (rc)
|
|
||||||
errno = _assuan_sock_wsa2errno (WSAGetLastError ());
|
|
||||||
if (rc && WSAGetLastError () == WSAENOTSOCK)
|
|
||||||
{
|
|
||||||
rc = CloseHandle (fd);
|
|
||||||
if (rc)
|
|
||||||
/* FIXME. */
|
|
||||||
errno = EIO;
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
#else
|
|
||||||
return close (fd);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Return a new socket. Note that under W32 we consider a socket the
|
|
||||||
same as an System Handle; all functions using such a handle know
|
|
||||||
about this dual use and act accordingly. */
|
|
||||||
assuan_fd_t
|
|
||||||
_assuan_sock_new (int domain, int type, int proto)
|
|
||||||
{
|
|
||||||
#ifdef HAVE_W32_SYSTEM
|
|
||||||
assuan_fd_t res;
|
|
||||||
if (domain == AF_UNIX || domain == AF_LOCAL)
|
|
||||||
domain = AF_INET;
|
|
||||||
|
|
||||||
#ifdef _ASSUAN_CUSTOM_IO
|
|
||||||
return _assuan_custom_socket (domain, type, proto);
|
|
||||||
#else
|
|
||||||
res = SOCKET2HANDLE(socket (domain, type, proto));
|
|
||||||
if (res == ASSUAN_INVALID_FD)
|
|
||||||
errno = _assuan_sock_wsa2errno (WSAGetLastError ());
|
|
||||||
return res;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#ifdef _ASSUAN_CUSTOM_IO
|
|
||||||
return _gpgme_io_socket (domain, type, proto);
|
|
||||||
#else
|
|
||||||
return socket (domain, type, proto);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
_assuan_sock_connect (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen)
|
|
||||||
{
|
|
||||||
#ifdef HAVE_W32_SYSTEM
|
|
||||||
if (addr->sa_family == AF_LOCAL || addr->sa_family == AF_UNIX)
|
|
||||||
{
|
|
||||||
struct sockaddr_in myaddr;
|
|
||||||
struct sockaddr_un *unaddr;
|
|
||||||
unsigned short port;
|
|
||||||
char nonce[16];
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
unaddr = (struct sockaddr_un *)addr;
|
|
||||||
if (read_port_and_nonce (unaddr->sun_path, &port, nonce))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
myaddr.sin_family = AF_INET;
|
|
||||||
myaddr.sin_port = htons (port);
|
|
||||||
myaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
|
|
||||||
|
|
||||||
/* Set return values. */
|
|
||||||
unaddr->sun_family = myaddr.sin_family;
|
|
||||||
unaddr->sun_port = myaddr.sin_port;
|
|
||||||
unaddr->sun_addr.s_addr = myaddr.sin_addr.s_addr;
|
|
||||||
|
|
||||||
#ifdef _ASSUAN_CUSTOM_IO
|
|
||||||
ret = _assuan_custom_connect (sockfd,
|
|
||||||
(struct sockaddr *)&myaddr, sizeof myaddr);
|
|
||||||
#else
|
|
||||||
ret = connect (HANDLE2SOCKET(sockfd),
|
|
||||||
(struct sockaddr *)&myaddr, sizeof myaddr);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!ret)
|
|
||||||
{
|
|
||||||
/* Send the nonce. */
|
|
||||||
|
|
||||||
ret = _assuan_io_write (sockfd, nonce, 16);
|
|
||||||
if (ret >= 0 && ret != 16)
|
|
||||||
{
|
|
||||||
errno = EIO;
|
|
||||||
ret = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
errno = _assuan_sock_wsa2errno (WSAGetLastError ());
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int res;
|
|
||||||
res = connect (HANDLE2SOCKET (sockfd), addr, addrlen);
|
|
||||||
if (res < 0)
|
|
||||||
errno = _assuan_sock_wsa2errno (WSAGetLastError ());
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
|
|
||||||
#ifdef _ASSUAN_CUSTOM_IO
|
|
||||||
return _assuan_custom_connect (sockfd, addr, addrlen);
|
|
||||||
#else
|
|
||||||
return connect (sockfd, addr, addrlen);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
_assuan_sock_bind (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen)
|
|
||||||
{
|
|
||||||
#ifdef HAVE_W32_SYSTEM
|
|
||||||
if (addr->sa_family == AF_LOCAL || addr->sa_family == AF_UNIX)
|
|
||||||
{
|
|
||||||
struct sockaddr_in myaddr;
|
|
||||||
struct sockaddr_un *unaddr;
|
|
||||||
int filefd;
|
|
||||||
FILE *fp;
|
|
||||||
int len = sizeof myaddr;
|
|
||||||
int rc;
|
|
||||||
char nonce[16];
|
|
||||||
|
|
||||||
if (get_nonce (nonce, 16))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
unaddr = (struct sockaddr_un *)addr;
|
|
||||||
|
|
||||||
myaddr.sin_port = 0;
|
|
||||||
myaddr.sin_family = AF_INET;
|
|
||||||
myaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
|
|
||||||
|
|
||||||
filefd = open (unaddr->sun_path,
|
|
||||||
(O_WRONLY|O_CREAT|O_EXCL|O_BINARY),
|
|
||||||
(S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP));
|
|
||||||
if (filefd == -1)
|
|
||||||
{
|
|
||||||
if (errno == EEXIST)
|
|
||||||
errno = WSAEADDRINUSE;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
fp = fdopen (filefd, "wb");
|
|
||||||
if (!fp)
|
|
||||||
{
|
|
||||||
int save_e = errno;
|
|
||||||
close (filefd);
|
|
||||||
errno = save_e;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = bind (HANDLE2SOCKET (sockfd), (struct sockaddr *)&myaddr, len);
|
|
||||||
if (!rc)
|
|
||||||
rc = getsockname (HANDLE2SOCKET (sockfd),
|
|
||||||
(struct sockaddr *)&myaddr, &len);
|
|
||||||
if (rc)
|
|
||||||
{
|
|
||||||
int save_e = errno;
|
|
||||||
fclose (fp);
|
|
||||||
remove (unaddr->sun_path);
|
|
||||||
errno = save_e;
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
fprintf (fp, "%d\n", ntohs (myaddr.sin_port));
|
|
||||||
fwrite (nonce, 16, 1, fp);
|
|
||||||
fclose (fp);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int res = bind (HANDLE2SOCKET(sockfd), addr, addrlen);
|
|
||||||
if (res < 0)
|
|
||||||
errno = _assuan_sock_wsa2errno (WSAGetLastError ());
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
return bind (sockfd, addr, addrlen);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
_assuan_sock_get_nonce (struct sockaddr *addr, int addrlen,
|
|
||||||
assuan_sock_nonce_t *nonce)
|
|
||||||
{
|
|
||||||
#ifdef HAVE_W32_SYSTEM
|
|
||||||
if (addr->sa_family == AF_LOCAL || addr->sa_family == AF_UNIX)
|
|
||||||
{
|
|
||||||
struct sockaddr_un *unaddr;
|
|
||||||
unsigned short port;
|
|
||||||
|
|
||||||
if (sizeof nonce->nonce != 16)
|
|
||||||
{
|
|
||||||
errno = EINVAL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
nonce->length = 16;
|
|
||||||
unaddr = (struct sockaddr_un *)addr;
|
|
||||||
if (read_port_and_nonce (unaddr->sun_path, &port, nonce->nonce))
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nonce->length = 42; /* Arbitrary valuie to detect unitialized nonce. */
|
|
||||||
nonce->nonce[0] = 42;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
(void)addr;
|
|
||||||
(void)addrlen;
|
|
||||||
nonce->length = 0;
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
_assuan_sock_check_nonce (assuan_fd_t fd, assuan_sock_nonce_t *nonce)
|
|
||||||
{
|
|
||||||
#ifdef HAVE_W32_SYSTEM
|
|
||||||
char buffer[16], *p;
|
|
||||||
size_t nleft;
|
|
||||||
int n;
|
|
||||||
|
|
||||||
if (sizeof nonce->nonce != 16)
|
|
||||||
{
|
|
||||||
errno = EINVAL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nonce->length == 42 && nonce->nonce[0] == 42)
|
|
||||||
return 0; /* Not a Unix domain socket. */
|
|
||||||
|
|
||||||
if (nonce->length != 16)
|
|
||||||
{
|
|
||||||
errno = EINVAL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
p = buffer;
|
|
||||||
nleft = 16;
|
|
||||||
while (nleft)
|
|
||||||
{
|
|
||||||
n = _assuan_io_read (SOCKET2HANDLE(fd), p, nleft);
|
|
||||||
if (n < 0 && errno == EINTR)
|
|
||||||
;
|
|
||||||
else if (n < 0 && errno == EAGAIN)
|
|
||||||
Sleep (100);
|
|
||||||
else if (n < 0)
|
|
||||||
return -1;
|
|
||||||
else if (!n)
|
|
||||||
{
|
|
||||||
errno = EIO;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
p += n;
|
|
||||||
nleft -= n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (memcmp (buffer, nonce->nonce, 16))
|
|
||||||
{
|
|
||||||
errno = EACCES;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
(void)fd;
|
|
||||||
(void)nonce;
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Public API. */
|
|
||||||
int
|
|
||||||
assuan_sock_close (assuan_fd_t fd)
|
|
||||||
{
|
|
||||||
return _assuan_close (fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
assuan_fd_t
|
|
||||||
assuan_sock_new (int domain, int type, int proto)
|
|
||||||
{
|
|
||||||
return _assuan_sock_new (domain, type, proto);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
assuan_sock_connect (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen)
|
|
||||||
{
|
|
||||||
return _assuan_sock_connect (sockfd, addr, addrlen);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
assuan_sock_bind (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen)
|
|
||||||
{
|
|
||||||
return _assuan_sock_bind (sockfd, addr, addrlen);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
assuan_sock_get_nonce (struct sockaddr *addr, int addrlen,
|
|
||||||
assuan_sock_nonce_t *nonce)
|
|
||||||
{
|
|
||||||
return _assuan_sock_get_nonce (addr, addrlen, nonce);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
assuan_sock_check_nonce (assuan_fd_t fd, assuan_sock_nonce_t *nonce)
|
|
||||||
{
|
|
||||||
return _assuan_sock_check_nonce (fd, nonce);
|
|
||||||
}
|
|
@ -1,313 +0,0 @@
|
|||||||
/* assuan-uds.c - Assuan unix domain socket utilities
|
|
||||||
* Copyright (C) 2006 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include <config.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#ifndef HAVE_W32_SYSTEM
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/un.h>
|
|
||||||
#else
|
|
||||||
#include <windows.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_UIO_H
|
|
||||||
#include <sys/uio.h>
|
|
||||||
#endif
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "assuan-defs.h"
|
|
||||||
|
|
||||||
#ifdef USE_DESCRIPTOR_PASSING
|
|
||||||
/* Provide replacement for missing CMSG maccros. We assume that
|
|
||||||
size_t matches the alignment requirement. */
|
|
||||||
#define MY_ALIGN(n) ((((n))+ sizeof(size_t)-1) & (size_t)~(sizeof(size_t)-1))
|
|
||||||
#ifndef CMSG_SPACE
|
|
||||||
#define CMSG_SPACE(n) (MY_ALIGN(sizeof(struct cmsghdr)) + MY_ALIGN((n)))
|
|
||||||
#endif
|
|
||||||
#ifndef CMSG_LEN
|
|
||||||
#define CMSG_LEN(n) (MY_ALIGN(sizeof(struct cmsghdr)) + (n))
|
|
||||||
#endif
|
|
||||||
#ifndef CMSG_FIRSTHDR
|
|
||||||
#define CMSG_FIRSTHDR(mhdr) \
|
|
||||||
((size_t)(mhdr)->msg_controllen >= sizeof (struct cmsghdr) \
|
|
||||||
? (struct cmsghdr*) (mhdr)->msg_control : (struct cmsghdr*)NULL)
|
|
||||||
#endif
|
|
||||||
#ifndef CMSG_DATA
|
|
||||||
#define CMSG_DATA(cmsg) ((unsigned char*)((struct cmsghdr*)(cmsg)+1))
|
|
||||||
#endif
|
|
||||||
#endif /*USE_DESCRIPTOR_PASSING*/
|
|
||||||
|
|
||||||
|
|
||||||
/* Read from a unix domain socket using sendmsg.
|
|
||||||
|
|
||||||
FIXME: We don't need the buffering. It is a leftover from the time
|
|
||||||
when we used datagrams. */
|
|
||||||
static ssize_t
|
|
||||||
uds_reader (assuan_context_t ctx, void *buf, size_t buflen)
|
|
||||||
{
|
|
||||||
#ifndef HAVE_W32_SYSTEM
|
|
||||||
int len = ctx->uds.buffersize;
|
|
||||||
|
|
||||||
if (!ctx->uds.bufferallocated)
|
|
||||||
{
|
|
||||||
ctx->uds.buffer = xtrymalloc (2048);
|
|
||||||
if (!ctx->uds.buffer)
|
|
||||||
return _assuan_error (ASSUAN_Out_Of_Core);
|
|
||||||
ctx->uds.bufferallocated = 2048;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!len) /* No data is buffered. */
|
|
||||||
{
|
|
||||||
struct msghdr msg;
|
|
||||||
struct iovec iovec;
|
|
||||||
#ifdef USE_DESCRIPTOR_PASSING
|
|
||||||
union {
|
|
||||||
struct cmsghdr cm;
|
|
||||||
char control[CMSG_SPACE(sizeof (int))];
|
|
||||||
} control_u;
|
|
||||||
struct cmsghdr *cmptr;
|
|
||||||
#endif /*USE_DESCRIPTOR_PASSING*/
|
|
||||||
|
|
||||||
memset (&msg, 0, sizeof (msg));
|
|
||||||
|
|
||||||
msg.msg_name = NULL;
|
|
||||||
msg.msg_namelen = 0;
|
|
||||||
msg.msg_iov = &iovec;
|
|
||||||
msg.msg_iovlen = 1;
|
|
||||||
iovec.iov_base = ctx->uds.buffer;
|
|
||||||
iovec.iov_len = ctx->uds.bufferallocated;
|
|
||||||
#ifdef USE_DESCRIPTOR_PASSING
|
|
||||||
msg.msg_control = control_u.control;
|
|
||||||
msg.msg_controllen = sizeof (control_u.control);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
len = _assuan_simple_recvmsg (ctx, &msg);
|
|
||||||
if (len < 0)
|
|
||||||
return -1;
|
|
||||||
if (len == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
ctx->uds.buffersize = len;
|
|
||||||
ctx->uds.bufferoffset = 0;
|
|
||||||
|
|
||||||
#ifdef USE_DESCRIPTOR_PASSING
|
|
||||||
cmptr = CMSG_FIRSTHDR (&msg);
|
|
||||||
if (cmptr && cmptr->cmsg_len == CMSG_LEN (sizeof(int)))
|
|
||||||
{
|
|
||||||
if (cmptr->cmsg_level != SOL_SOCKET
|
|
||||||
|| cmptr->cmsg_type != SCM_RIGHTS)
|
|
||||||
_assuan_log_printf ("unexpected ancillary data received\n");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int fd = *((int*)CMSG_DATA (cmptr));
|
|
||||||
|
|
||||||
if (ctx->uds.pendingfdscount >= DIM (ctx->uds.pendingfds))
|
|
||||||
{
|
|
||||||
_assuan_log_printf ("too many descriptors pending - "
|
|
||||||
"closing received descriptor %d\n", fd);
|
|
||||||
_assuan_close (fd);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ctx->uds.pendingfds[ctx->uds.pendingfdscount++] = fd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /*USE_DESCRIPTOR_PASSING*/
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return some data to the user. */
|
|
||||||
|
|
||||||
if (len > buflen) /* We have more than the user requested. */
|
|
||||||
len = buflen;
|
|
||||||
|
|
||||||
memcpy (buf, (char*)ctx->uds.buffer + ctx->uds.bufferoffset, len);
|
|
||||||
ctx->uds.buffersize -= len;
|
|
||||||
assert (ctx->uds.buffersize >= 0);
|
|
||||||
ctx->uds.bufferoffset += len;
|
|
||||||
assert (ctx->uds.bufferoffset <= ctx->uds.bufferallocated);
|
|
||||||
|
|
||||||
return len;
|
|
||||||
#else /*HAVE_W32_SYSTEM*/
|
|
||||||
int res = recvfrom (HANDLE2SOCKET(ctx->inbound.fd), buf, buflen, 0, NULL, NULL);
|
|
||||||
if (res < 0)
|
|
||||||
errno = _assuan_sock_wsa2errno (WSAGetLastError ());
|
|
||||||
return res;
|
|
||||||
#endif /*HAVE_W32_SYSTEM*/
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Write to the domain server. */
|
|
||||||
static ssize_t
|
|
||||||
uds_writer (assuan_context_t ctx, const void *buf, size_t buflen)
|
|
||||||
{
|
|
||||||
#ifndef HAVE_W32_SYSTEM
|
|
||||||
struct msghdr msg;
|
|
||||||
struct iovec iovec;
|
|
||||||
ssize_t len;
|
|
||||||
|
|
||||||
memset (&msg, 0, sizeof (msg));
|
|
||||||
|
|
||||||
msg.msg_name = NULL;
|
|
||||||
msg.msg_namelen = 0;
|
|
||||||
msg.msg_iovlen = 1;
|
|
||||||
msg.msg_iov = &iovec;
|
|
||||||
iovec.iov_base = (void*)buf;
|
|
||||||
iovec.iov_len = buflen;
|
|
||||||
|
|
||||||
len = _assuan_simple_sendmsg (ctx, &msg);
|
|
||||||
|
|
||||||
return len;
|
|
||||||
#else /*HAVE_W32_SYSTEM*/
|
|
||||||
int res = sendto (HANDLE2SOCKET(ctx->outbound.fd), buf, buflen, 0,
|
|
||||||
(struct sockaddr *)&ctx->serveraddr,
|
|
||||||
sizeof (struct sockaddr_in));
|
|
||||||
if (res < 0)
|
|
||||||
errno = _assuan_sock_wsa2errno (WSAGetLastError ());
|
|
||||||
return res;
|
|
||||||
#endif /*HAVE_W32_SYSTEM*/
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static assuan_error_t
|
|
||||||
uds_sendfd (assuan_context_t ctx, assuan_fd_t fd)
|
|
||||||
{
|
|
||||||
#ifdef USE_DESCRIPTOR_PASSING
|
|
||||||
struct msghdr msg;
|
|
||||||
struct iovec iovec;
|
|
||||||
union {
|
|
||||||
struct cmsghdr cm;
|
|
||||||
char control[CMSG_SPACE(sizeof (int))];
|
|
||||||
} control_u;
|
|
||||||
struct cmsghdr *cmptr;
|
|
||||||
int len;
|
|
||||||
char buffer[80];
|
|
||||||
|
|
||||||
/* We need to send some real data so that a read won't return 0
|
|
||||||
which will be taken as an EOF. It also helps with debugging. */
|
|
||||||
snprintf (buffer, sizeof(buffer)-1, "# descriptor %d is in flight\n", fd);
|
|
||||||
buffer[sizeof(buffer)-1] = 0;
|
|
||||||
|
|
||||||
memset (&msg, 0, sizeof (msg));
|
|
||||||
|
|
||||||
msg.msg_name = NULL;
|
|
||||||
msg.msg_namelen = 0;
|
|
||||||
msg.msg_iovlen = 1;
|
|
||||||
msg.msg_iov = &iovec;
|
|
||||||
iovec.iov_base = buffer;
|
|
||||||
iovec.iov_len = strlen (buffer);
|
|
||||||
|
|
||||||
msg.msg_control = control_u.control;
|
|
||||||
msg.msg_controllen = sizeof (control_u.control);
|
|
||||||
cmptr = CMSG_FIRSTHDR (&msg);
|
|
||||||
cmptr->cmsg_len = CMSG_LEN(sizeof(int));
|
|
||||||
cmptr->cmsg_level = SOL_SOCKET;
|
|
||||||
cmptr->cmsg_type = SCM_RIGHTS;
|
|
||||||
*((int*)CMSG_DATA (cmptr)) = fd;
|
|
||||||
|
|
||||||
len = _assuan_simple_sendmsg (ctx, &msg);
|
|
||||||
if (len < 0)
|
|
||||||
{
|
|
||||||
_assuan_log_printf ("uds_sendfd: %s\n", strerror (errno));
|
|
||||||
return _assuan_error (ASSUAN_Write_Error);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
#else
|
|
||||||
return _assuan_error (ASSUAN_Not_Implemented);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static assuan_error_t
|
|
||||||
uds_receivefd (assuan_context_t ctx, assuan_fd_t *fd)
|
|
||||||
{
|
|
||||||
#ifdef USE_DESCRIPTOR_PASSING
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (!ctx->uds.pendingfdscount)
|
|
||||||
{
|
|
||||||
_assuan_log_printf ("no pending file descriptors!\n");
|
|
||||||
return _assuan_error (ASSUAN_General_Error);
|
|
||||||
}
|
|
||||||
assert (ctx->uds.pendingfdscount <= DIM(ctx->uds.pendingfds));
|
|
||||||
|
|
||||||
*fd = ctx->uds.pendingfds[0];
|
|
||||||
for (i=1; i < ctx->uds.pendingfdscount; i++)
|
|
||||||
ctx->uds.pendingfds[i-1] = ctx->uds.pendingfds[i];
|
|
||||||
ctx->uds.pendingfdscount--;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
#else
|
|
||||||
return _assuan_error (ASSUAN_Not_Implemented);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Close all pending fds. */
|
|
||||||
void
|
|
||||||
_assuan_uds_close_fds (assuan_context_t ctx)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < ctx->uds.pendingfdscount; i++)
|
|
||||||
_assuan_close (ctx->uds.pendingfds[i]);
|
|
||||||
ctx->uds.pendingfdscount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Deinitialize the unix domain socket I/O functions. */
|
|
||||||
void
|
|
||||||
_assuan_uds_deinit (assuan_context_t ctx)
|
|
||||||
{
|
|
||||||
/* First call the finish_handler which should close descriptors etc. */
|
|
||||||
ctx->finish_handler (ctx);
|
|
||||||
|
|
||||||
if (ctx->uds.buffer)
|
|
||||||
{
|
|
||||||
assert (ctx->uds.bufferallocated);
|
|
||||||
ctx->uds.bufferallocated = 0;
|
|
||||||
xfree (ctx->uds.buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
_assuan_uds_close_fds (ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Helper function to initialize a context for domain I/O. */
|
|
||||||
void
|
|
||||||
_assuan_init_uds_io (assuan_context_t ctx)
|
|
||||||
{
|
|
||||||
static struct assuan_io io = { uds_reader, uds_writer,
|
|
||||||
uds_sendfd, uds_receivefd };
|
|
||||||
|
|
||||||
ctx->io = &io;
|
|
||||||
ctx->uds.buffer = 0;
|
|
||||||
ctx->uds.bufferoffset = 0;
|
|
||||||
ctx->uds.buffersize = 0;
|
|
||||||
ctx->uds.bufferallocated = 0;
|
|
||||||
ctx->uds.pendingfdscount = 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,188 +0,0 @@
|
|||||||
/* assuan-util.c - Utility functions for Assuan
|
|
||||||
* Copyright (C) 2001, 2002, 2003, 2004, 2005 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include "assuan-defs.h"
|
|
||||||
|
|
||||||
static void *(*alloc_func)(size_t n) = malloc;
|
|
||||||
static void *(*realloc_func)(void *p, size_t n) = realloc;
|
|
||||||
static void (*free_func)(void*) = free;
|
|
||||||
|
|
||||||
struct assuan_io_hooks _assuan_io_hooks;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
assuan_set_malloc_hooks ( void *(*new_alloc_func)(size_t n),
|
|
||||||
void *(*new_realloc_func)(void *p, size_t n),
|
|
||||||
void (*new_free_func)(void*) )
|
|
||||||
{
|
|
||||||
alloc_func = new_alloc_func;
|
|
||||||
realloc_func = new_realloc_func;
|
|
||||||
free_func = new_free_func;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
assuan_set_io_hooks (assuan_io_hooks_t io_hooks)
|
|
||||||
{
|
|
||||||
_assuan_io_hooks.read_hook = NULL;
|
|
||||||
_assuan_io_hooks.write_hook = NULL;
|
|
||||||
if (io_hooks)
|
|
||||||
{
|
|
||||||
_assuan_io_hooks.read_hook = io_hooks->read_hook;
|
|
||||||
_assuan_io_hooks.write_hook = io_hooks->write_hook;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void *
|
|
||||||
_assuan_malloc (size_t n)
|
|
||||||
{
|
|
||||||
return alloc_func (n);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *
|
|
||||||
_assuan_realloc (void *a, size_t n)
|
|
||||||
{
|
|
||||||
return realloc_func (a, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *
|
|
||||||
_assuan_calloc (size_t n, size_t m)
|
|
||||||
{
|
|
||||||
void *p;
|
|
||||||
size_t nbytes;
|
|
||||||
|
|
||||||
nbytes = n * m;
|
|
||||||
if (m && nbytes / m != n)
|
|
||||||
{
|
|
||||||
errno = ENOMEM;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
p = _assuan_malloc (nbytes);
|
|
||||||
if (p)
|
|
||||||
memset (p, 0, nbytes);
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
_assuan_free (void *p)
|
|
||||||
{
|
|
||||||
if (p)
|
|
||||||
free_func (p);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Store the error in the context so that the error sending function
|
|
||||||
can take out a descriptive text. Inside the assuan code, use the
|
|
||||||
macro set_error instead of this function. */
|
|
||||||
int
|
|
||||||
assuan_set_error (assuan_context_t ctx, int err, const char *text)
|
|
||||||
{
|
|
||||||
ctx->err_no = err;
|
|
||||||
ctx->err_str = text;
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
assuan_set_pointer (assuan_context_t ctx, void *pointer)
|
|
||||||
{
|
|
||||||
if (ctx)
|
|
||||||
ctx->user_pointer = pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *
|
|
||||||
assuan_get_pointer (assuan_context_t ctx)
|
|
||||||
{
|
|
||||||
return ctx? ctx->user_pointer : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
assuan_begin_confidential (assuan_context_t ctx)
|
|
||||||
{
|
|
||||||
if (ctx)
|
|
||||||
{
|
|
||||||
ctx->confidential = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
assuan_end_confidential (assuan_context_t ctx)
|
|
||||||
{
|
|
||||||
if (ctx)
|
|
||||||
{
|
|
||||||
ctx->confidential = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
assuan_set_io_monitor (assuan_context_t ctx,
|
|
||||||
unsigned int (*monitor)(assuan_context_t ctx,
|
|
||||||
int direction,
|
|
||||||
const char *line,
|
|
||||||
size_t linelen))
|
|
||||||
{
|
|
||||||
if (ctx)
|
|
||||||
{
|
|
||||||
ctx->io_monitor = monitor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* For context CTX, set the flag FLAG to VALUE. Values for flags
|
|
||||||
are usually 1 or 0 but certain flags might allow for other values;
|
|
||||||
see the description of the type assuan_flag_t for details. */
|
|
||||||
void
|
|
||||||
assuan_set_flag (assuan_context_t ctx, assuan_flag_t flag, int value)
|
|
||||||
{
|
|
||||||
if (!ctx)
|
|
||||||
return;
|
|
||||||
switch (flag)
|
|
||||||
{
|
|
||||||
case ASSUAN_NO_WAITPID: ctx->flags.no_waitpid = value; break;
|
|
||||||
case ASSUAN_CONFIDENTIAL: ctx->confidential = value; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return the VALUE of FLAG in context CTX. */
|
|
||||||
int
|
|
||||||
assuan_get_flag (assuan_context_t ctx, assuan_flag_t flag)
|
|
||||||
{
|
|
||||||
if (!ctx)
|
|
||||||
return 0;
|
|
||||||
switch (flag)
|
|
||||||
{
|
|
||||||
case ASSUAN_NO_WAITPID: return ctx->flags.no_waitpid;
|
|
||||||
case ASSUAN_CONFIDENTIAL: return ctx->confidential;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
700
assuan/assuan.h
700
assuan/assuan.h
@ -1,700 +0,0 @@
|
|||||||
/* assuan.h - Definitions for the Assuan IPC library
|
|
||||||
* Copyright (C) 2001, 2002, 2003, 2005, 2007,
|
|
||||||
* 2008 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef ASSUAN_H
|
|
||||||
#define ASSUAN_H
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#ifndef _ASSUAN_NO_SOCKET_WRAPPER
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <ws2tcpip.h>
|
|
||||||
#else
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#endif
|
|
||||||
#endif /*!_ASSUAN_NO_SOCKET_WRAPPER*/
|
|
||||||
|
|
||||||
/* To use this file with libraries the following macros are useful:
|
|
||||||
|
|
||||||
#define _ASSUAN_EXT_SYM_PREFIX _foo_
|
|
||||||
|
|
||||||
This prefixes all external symbols with "_foo_".
|
|
||||||
|
|
||||||
#define _ASSUAN_ONLY_GPG_ERRORS
|
|
||||||
|
|
||||||
If this is defined all old-style Assuan error codes are made
|
|
||||||
inactive as well as other deprecated stuff.
|
|
||||||
|
|
||||||
#define _ASSUAN_NO_SOCKET_WRAPPER
|
|
||||||
|
|
||||||
Do not include the definitions for the socket wrapper feature.
|
|
||||||
|
|
||||||
The follwing macros are used internally in the implementation of
|
|
||||||
libassuan:
|
|
||||||
|
|
||||||
#define _ASSUAN_NO_PTH
|
|
||||||
|
|
||||||
This avoids inclusion of special GNU Pth hacks.
|
|
||||||
|
|
||||||
#define _ASSUAN_NO_FIXED_SIGNALS
|
|
||||||
|
|
||||||
This disables changing of certain signal handler; i.e. SIGPIPE.
|
|
||||||
|
|
||||||
#define _ASSUAN_USE_DOUBLE_FORK
|
|
||||||
|
|
||||||
Use a double fork approach when connecting to a server through
|
|
||||||
a pipe.
|
|
||||||
*/
|
|
||||||
/**** Begin GPGME specific modifications. ******/
|
|
||||||
#define _ASSUAN_EXT_SYM_PREFIX _gpgme_
|
|
||||||
#define _ASSUAN_NO_PTH
|
|
||||||
#define _ASSUAN_NO_FIXED_SIGNALS
|
|
||||||
#define _ASSUAN_USE_DOUBLE_FORK
|
|
||||||
|
|
||||||
#ifdef _ASSUAN_IN_GPGME_BUILD_ASSUAN
|
|
||||||
#include <ath.h>
|
|
||||||
|
|
||||||
int _gpgme_io_close (int fd);
|
|
||||||
int _gpgme_io_read (int fd, void *buffer, size_t count);
|
|
||||||
int _gpgme_io_write (int fd, const void *buffer, size_t count);
|
|
||||||
int _gpgme_io_connect (int fd, struct sockaddr *addr, int addrlen);
|
|
||||||
int _gpgme_io_sendmsg (int sock, const struct msghdr *msg, int flags);
|
|
||||||
int _gpgme_io_recvmsg (int sock, struct msghdr *msg, int flags);
|
|
||||||
int _gpgme_io_socket (int domain, int type, int proto);
|
|
||||||
|
|
||||||
#define _assuan_funopen _gpgme_funopen
|
|
||||||
|
|
||||||
#define close _gpgme_io_close
|
|
||||||
#define read _gpgme_io_read
|
|
||||||
#define write _gpgme_io_write
|
|
||||||
#define waitpid _gpgme_ath_waitpid
|
|
||||||
#define select _gpgme_ath_select
|
|
||||||
#define accept _gpgme_ath_accept
|
|
||||||
#define connect _gpgme_ath_connect
|
|
||||||
#define sendmsg _gpgme_io_sendmsg
|
|
||||||
#define recvmsg _gpgme_io_recvmsg
|
|
||||||
#endif /*_ASSUAN_IN_GPGME_BUILD_ASSUAN*/
|
|
||||||
|
|
||||||
#define _ASSUAN_CUSTOM_IO 1
|
|
||||||
#define _assuan_custom_close _gpgme_io_close
|
|
||||||
#define _assuan_custom_read _gpgme_io_read
|
|
||||||
#define _assuan_custom_write _gpgme_io_write
|
|
||||||
#define _assuan_custom_pipe _gpgme_io_pipe
|
|
||||||
#define _assuan_custom_socket _gpgme_io_socket
|
|
||||||
#define _assuan_custom_connect _gpgme_io_connect
|
|
||||||
|
|
||||||
/**** End GPGME specific modifications. ******/
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef _ASSUAN_EXT_SYM_PREFIX
|
|
||||||
#define _ASSUAN_PREFIX1(x,y) x ## y
|
|
||||||
#define _ASSUAN_PREFIX2(x,y) _ASSUAN_PREFIX1(x,y)
|
|
||||||
#define _ASSUAN_PREFIX(x) _ASSUAN_PREFIX2(_ASSUAN_EXT_SYM_PREFIX,x)
|
|
||||||
#define assuan_ _ASSUAN_PREFIX(assuan_)
|
|
||||||
#define assuan_register_command _ASSUAN_PREFIX(assuan_register_command)
|
|
||||||
#define assuan_register_post_cmd_notify \
|
|
||||||
_ASSUAN_PREFIX(assuan_register_post_cmd_notify)
|
|
||||||
#define assuan_register_bye_notify _ASSUAN_PREFIX(assuan_register_bye_notify)
|
|
||||||
#define assuan_register_reset_notify \
|
|
||||||
_ASSUAN_PREFIX(assuan_register_reset_notify)
|
|
||||||
#define assuan_register_cancel_notify \
|
|
||||||
_ASSUAN_PREFIX(assuan_register_cancel_notify)
|
|
||||||
#define assuan_register_input_notify \
|
|
||||||
_ASSUAN_PREFIX(assuan_register_input_notify)
|
|
||||||
#define assuan_register_output_notify \
|
|
||||||
_ASSUAN_PREFIX(assuan_register_output_notify)
|
|
||||||
#define assuan_register_option_handler \
|
|
||||||
_ASSUAN_PREFIX(assuan_register_option_handler)
|
|
||||||
#define assuan_process _ASSUAN_PREFIX(assuan_process)
|
|
||||||
#define assuan_process_next _ASSUAN_PREFIX(assuan_process_next)
|
|
||||||
#define assuan_process_done _ASSUAN_PREFIX(assuan_process_done)
|
|
||||||
#define assuan_get_active_fds _ASSUAN_PREFIX(assuan_get_active_fds)
|
|
||||||
#define assuan_get_data_fp _ASSUAN_PREFIX(assuan_get_data_fp)
|
|
||||||
#define assuan_set_okay_line _ASSUAN_PREFIX(assuan_set_okay_line)
|
|
||||||
#define assuan_write_status _ASSUAN_PREFIX(assuan_write_status)
|
|
||||||
#define assuan_command_parse_fd _ASSUAN_PREFIX(assuan_command_parse_fd)
|
|
||||||
#define assuan_set_hello_line _ASSUAN_PREFIX(assuan_set_hello_line)
|
|
||||||
#define assuan_accept _ASSUAN_PREFIX(assuan_accept)
|
|
||||||
#define assuan_get_input_fd _ASSUAN_PREFIX(assuan_get_input_fd)
|
|
||||||
#define assuan_get_output_fd _ASSUAN_PREFIX(assuan_get_output_fd)
|
|
||||||
#define assuan_close_input_fd _ASSUAN_PREFIX(assuan_close_input_fd)
|
|
||||||
#define assuan_close_output_fd _ASSUAN_PREFIX(assuan_close_output_fd)
|
|
||||||
#define assuan_init_pipe_server _ASSUAN_PREFIX(assuan_init_pipe_server)
|
|
||||||
#define assuan_deinit_server _ASSUAN_PREFIX(assuan_deinit_server)
|
|
||||||
#define assuan_init_socket_server _ASSUAN_PREFIX(assuan_init_socket_server)
|
|
||||||
#define assuan_init_connected_socket_server \
|
|
||||||
_ASSUAN_PREFIX(assuan_init_connected_socket_server)
|
|
||||||
#define assuan_init_socket_server_ext \
|
|
||||||
_ASSUAN_PREFIX(assuan_init_socket_server_ext)
|
|
||||||
#define assuan_pipe_connect _ASSUAN_PREFIX(assuan_pipe_connect)
|
|
||||||
#define assuan_pipe_connect_ext _ASSUAN_PREFIX(assuan_pipe_connect_ext)
|
|
||||||
#define assuan_socket_connect _ASSUAN_PREFIX(assuan_socket_connect)
|
|
||||||
#define assuan_socket_connect_ext _ASSUAN_PREFIX(assuan_socket_connect_ext)
|
|
||||||
#define assuan_disconnect _ASSUAN_PREFIX(assuan_disconnect)
|
|
||||||
#define assuan_get_pid _ASSUAN_PREFIX(assuan_get_pid)
|
|
||||||
#define assuan_get_peercred _ASSUAN_PREFIX(assuan_get_peercred)
|
|
||||||
#define assuan_transact _ASSUAN_PREFIX(assuan_transact)
|
|
||||||
#define assuan_inquire _ASSUAN_PREFIX(assuan_inquire)
|
|
||||||
#define assuan_inquire_ext _ASSUAN_PREFIX(assuan_inquire_ext)
|
|
||||||
#define assuan_read_line _ASSUAN_PREFIX(assuan_read_line)
|
|
||||||
#define assuan_pending_line _ASSUAN_PREFIX(assuan_pending_line)
|
|
||||||
#define assuan_write_line _ASSUAN_PREFIX(assuan_write_line)
|
|
||||||
#define assuan_send_data _ASSUAN_PREFIX(assuan_send_data)
|
|
||||||
#define assuan_sendfd _ASSUAN_PREFIX(assuan_sendfd)
|
|
||||||
#define assuan_receivefd _ASSUAN_PREFIX(assuan_receivefd)
|
|
||||||
#define assuan_set_malloc_hooks _ASSUAN_PREFIX(assuan_set_malloc_hooks)
|
|
||||||
#define assuan_set_io_hooks _ASSUAN_PREFIX(assuan_set_io_hooks)
|
|
||||||
#define assuan_set_log_stream _ASSUAN_PREFIX(assuan_set_log_stream)
|
|
||||||
#define assuan_set_error _ASSUAN_PREFIX(assuan_set_error)
|
|
||||||
#define assuan_set_pointer _ASSUAN_PREFIX(assuan_set_pointer)
|
|
||||||
#define assuan_get_pointer _ASSUAN_PREFIX(assuan_get_pointer)
|
|
||||||
#define assuan_set_io_monitor _ASSUAN_PREFIX(assuan_set_io_monitor)
|
|
||||||
#define assuan_begin_confidential _ASSUAN_PREFIX(assuan_begin_confidential)
|
|
||||||
#define assuan_end_confidential _ASSUAN_PREFIX(assuan_end_confidential)
|
|
||||||
#define assuan_strerror _ASSUAN_PREFIX(assuan_strerror)
|
|
||||||
#define assuan_set_assuan_err_source \
|
|
||||||
_ASSUAN_PREFIX(assuan_set_assuan_err_source)
|
|
||||||
#define assuan_set_assuan_log_stream \
|
|
||||||
_ASSUAN_PREFIX(assuan_set_assuan_log_stream)
|
|
||||||
#define assuan_get_assuan_log_stream \
|
|
||||||
_ASSUAN_PREFIX(assuan_get_assuan_log_stream)
|
|
||||||
#define assuan_get_assuan_log_prefix \
|
|
||||||
_ASSUAN_PREFIX(assuan_get_assuan_log_prefix)
|
|
||||||
#define assuan_set_flag _ASSUAN_PREFIX(assuan_set_flag)
|
|
||||||
#define assuan_get_flag _ASSUAN_PREFIX(assuan_get_flag)
|
|
||||||
#define assuan_pipe_connect2 _ASSUAN_PREFIX(assuan_pipe_connect2)
|
|
||||||
#define assuan_set_assuan_log_prefix \
|
|
||||||
_ASSUAN_PREFIX(assuan_set_assuan_log_prefix)
|
|
||||||
#define assuan_sock_close _ASSUAN_PREFIX(assuan_sock_close)
|
|
||||||
#define assuan_sock_new _ASSUAN_PREFIX(assuan_sock_new)
|
|
||||||
#define assuan_sock_connect _ASSUAN_PREFIX(assuan_sock_connect)
|
|
||||||
#define assuan_sock_bind _ASSUAN_PREFIX(assuan_sock_bind)
|
|
||||||
#define assuan_sock_get_nonce _ASSUAN_PREFIX(assuan_sock_get_nonce)
|
|
||||||
#define assuan_sock_check_nonce _ASSUAN_PREFIX(assuan_sock_check_nonce)
|
|
||||||
|
|
||||||
|
|
||||||
/* And now the internal functions, argh... */
|
|
||||||
#define _assuan_read_line _ASSUAN_PREFIX(_assuan_read_line)
|
|
||||||
#define _assuan_cookie_write_data _ASSUAN_PREFIX(_assuan_cookie_write_data)
|
|
||||||
#define _assuan_cookie_write_flush _ASSUAN_PREFIX(_assuan_cookie_write_flush)
|
|
||||||
#define _assuan_read_from_server _ASSUAN_PREFIX(_assuan_read_from_server)
|
|
||||||
#define _assuan_domain_init _ASSUAN_PREFIX(_assuan_domain_init)
|
|
||||||
#define _assuan_register_std_commands \
|
|
||||||
_ASSUAN_PREFIX(_assuan_register_std_commands)
|
|
||||||
#define _assuan_simple_read _ASSUAN_PREFIX(_assuan_simple_read)
|
|
||||||
#define _assuan_simple_write _ASSUAN_PREFIX(_assuan_simple_write)
|
|
||||||
#define _assuan_io_read _ASSUAN_PREFIX(_assuan_io_read)
|
|
||||||
#define _assuan_io_write _ASSUAN_PREFIX(_assuan_io_write)
|
|
||||||
#define _assuan_io_hooks _ASSUAN_PREFIX(_assuan_io_hooks)
|
|
||||||
#define _assuan_new_context _ASSUAN_PREFIX(_assuan_new_context)
|
|
||||||
#define _assuan_release_context _ASSUAN_PREFIX(_assuan_release_context)
|
|
||||||
#define _assuan_malloc _ASSUAN_PREFIX(_assuan_malloc)
|
|
||||||
#define _assuan_realloc _ASSUAN_PREFIX(_assuan_realloc)
|
|
||||||
#define _assuan_calloc _ASSUAN_PREFIX(_assuan_calloc)
|
|
||||||
#define _assuan_free _ASSUAN_PREFIX(_assuan_free)
|
|
||||||
#define _assuan_log_print_buffer _ASSUAN_PREFIX(_assuan_log_print_buffer)
|
|
||||||
#define _assuan_log_sanitized_string \
|
|
||||||
_ASSUAN_PREFIX(_assuan_log_sanitized_string)
|
|
||||||
#define _assuan_log_printf _ASSUAN_PREFIX(_assuan_log_printf)
|
|
||||||
#define _assuan_set_default_log_stream \
|
|
||||||
_ASSUAN_PREFIX(_assuan_set_default_log_stream)
|
|
||||||
#define _assuan_w32_strerror _ASSUAN_PREFIX(_assuan_w32_strerror)
|
|
||||||
#define _assuan_gpg_strerror_r _ASSUAN_PREFIX(_assuan_gpg_strerror_r)
|
|
||||||
#define _assuan_gpg_strsource _ASSUAN_PREFIX(_assuan_gpg_strsource)
|
|
||||||
#define _assuan_write_line _ASSUAN_PREFIX(_assuan_write_line)
|
|
||||||
#define _assuan_error _ASSUAN_PREFIX(_assuan_error)
|
|
||||||
#define _assuan_error_is_eagain _ASSUAN_PREFIX(_assuan_error_is_eagain)
|
|
||||||
#define _assuan_init_uds_io _ASSUAN_PREFIX(_assuan_init_uds_io)
|
|
||||||
#define _assuan_uds_close_fds _ASSUAN_PREFIX(_assuan_uds_close_fds)
|
|
||||||
#define _assuan_uds_deinit _ASSUAN_PREFIX(_assuan_uds_deinit)
|
|
||||||
#define _assuan_simple_recvmsg _ASSUAN_PREFIX(_assuan_simple_recvmsg)
|
|
||||||
#define _assuan_simple_sendmsg _ASSUAN_PREFIX(_assuan_simple_sendmsg)
|
|
||||||
#define _assuan_waitpid _ASSUAN_PREFIX(_assuan_waitpid)
|
|
||||||
#define _assuan_sock_wsa2errno _ASSUAN_PREFIX(_assuan_sock_wsa2errno)
|
|
||||||
#define _assuan_sock_close _ASSUAN_PREFIX(_assuan_sock_close)
|
|
||||||
#define _assuan_sock_new _ASSUAN_PREFIX(_assuan_sock_new)
|
|
||||||
#define _assuan_sock_connect _ASSUAN_PREFIX(_assuan_sock_connect)
|
|
||||||
#define _assuan_sock_bind _ASSUAN_PREFIX(_assuan_sock_bind)
|
|
||||||
#define _assuan_sock_get_nonce _ASSUAN_PREFIX(_assuan_sock_get_nonce)
|
|
||||||
#define _assuan_sock_check_nonce _ASSUAN_PREFIX(_assuan_sock_check_nonce)
|
|
||||||
#define _assuan_close _ASSUAN_PREFIX(_assuan_close)
|
|
||||||
#define _assuan_usleep _ASSUAN_PREFIX(_assuan_usleep)
|
|
||||||
|
|
||||||
#endif /*_ASSUAN_EXT_SYM_PREFIX*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* Check for compiler features. */
|
|
||||||
#if __GNUC__
|
|
||||||
#define _ASSUAN_GCC_VERSION (__GNUC__ * 10000 \
|
|
||||||
+ __GNUC_MINOR__ * 100 \
|
|
||||||
+ __GNUC_PATCHLEVEL__)
|
|
||||||
|
|
||||||
#if _ASSUAN_GCC_VERSION > 30100
|
|
||||||
#define _ASSUAN_DEPRECATED __attribute__ ((__deprecated__))
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#ifndef _ASSUAN_DEPRECATED
|
|
||||||
#define _ASSUAN_DEPRECATED
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* Assuan error codes. These are only used by old applications or
|
|
||||||
those applications which won't make use of libgpg-error. */
|
|
||||||
#ifndef _ASSUAN_ONLY_GPG_ERRORS
|
|
||||||
#ifndef _ASSUAN_IN_LIBASSUAN
|
|
||||||
#define ASSUAN_No_Error 0
|
|
||||||
#endif
|
|
||||||
#define ASSUAN_General_Error 1
|
|
||||||
#define ASSUAN_Out_Of_Core 2
|
|
||||||
#define ASSUAN_Invalid_Value 3
|
|
||||||
#ifndef _ASSUAN_IN_LIBASSUAN
|
|
||||||
#define ASSUAN_Timeout 4
|
|
||||||
#endif
|
|
||||||
#define ASSUAN_Read_Error 5
|
|
||||||
#define ASSUAN_Write_Error 6
|
|
||||||
#define ASSUAN_Problem_Starting_Server 7
|
|
||||||
#define ASSUAN_Not_A_Server 8
|
|
||||||
#ifndef _ASSUAN_IN_LIBASSUAN
|
|
||||||
#define ASSUAN_Not_A_Client 9
|
|
||||||
#endif
|
|
||||||
#define ASSUAN_Nested_Commands 10
|
|
||||||
#define ASSUAN_Invalid_Response 11
|
|
||||||
#define ASSUAN_No_Data_Callback 12
|
|
||||||
#define ASSUAN_No_Inquire_Callback 13
|
|
||||||
#define ASSUAN_Connect_Failed 14
|
|
||||||
#define ASSUAN_Accept_Failed 15
|
|
||||||
|
|
||||||
/* Error codes above 99 are meant as status codes */
|
|
||||||
#define ASSUAN_Not_Implemented 100
|
|
||||||
#define ASSUAN_Server_Fault 101
|
|
||||||
#ifndef _ASSUAN_IN_LIBASSUAN
|
|
||||||
#define ASSUAN_Invalid_Command 102
|
|
||||||
#endif
|
|
||||||
#define ASSUAN_Unknown_Command 103
|
|
||||||
#define ASSUAN_Syntax_Error 104
|
|
||||||
#ifndef _ASSUAN_IN_LIBASSUAN
|
|
||||||
#define ASSUAN_Parameter_Error 105
|
|
||||||
#endif
|
|
||||||
#define ASSUAN_Parameter_Conflict 106
|
|
||||||
#define ASSUAN_Line_Too_Long 107
|
|
||||||
#define ASSUAN_Line_Not_Terminated 108
|
|
||||||
#ifndef _ASSUAN_IN_LIBASSUAN
|
|
||||||
#define ASSUAN_No_Input 109
|
|
||||||
#define ASSUAN_No_Output 110
|
|
||||||
#endif
|
|
||||||
#define ASSUAN_Canceled 111
|
|
||||||
#ifndef _ASSUAN_IN_LIBASSUAN
|
|
||||||
#define ASSUAN_Unsupported_Algorithm 112
|
|
||||||
#define ASSUAN_Server_Resource_Problem 113
|
|
||||||
#define ASSUAN_Server_IO_Error 114
|
|
||||||
#define ASSUAN_Server_Bug 115
|
|
||||||
#define ASSUAN_No_Data_Available 116
|
|
||||||
#define ASSUAN_Invalid_Data 117
|
|
||||||
#endif
|
|
||||||
#define ASSUAN_Unexpected_Command 118
|
|
||||||
#define ASSUAN_Too_Much_Data 119
|
|
||||||
#ifndef _ASSUAN_IN_LIBASSUAN
|
|
||||||
#define ASSUAN_Inquire_Unknown 120
|
|
||||||
#define ASSUAN_Inquire_Error 121
|
|
||||||
#define ASSUAN_Invalid_Option 122
|
|
||||||
#define ASSUAN_Invalid_Index 123
|
|
||||||
#define ASSUAN_Unexpected_Status 124
|
|
||||||
#define ASSUAN_Unexpected_Data 125
|
|
||||||
#define ASSUAN_Invalid_Status 126
|
|
||||||
#define ASSUAN_Locale_Problem 127
|
|
||||||
#endif
|
|
||||||
#define ASSUAN_Not_Confirmed 128
|
|
||||||
|
|
||||||
/* Warning: Don't use the Error codes, below they are deprecated. */
|
|
||||||
#ifndef _ASSUAN_IN_LIBASSUAN
|
|
||||||
#define ASSUAN_Bad_Certificate 201
|
|
||||||
#define ASSUAN_Bad_Certificate_Chain 202
|
|
||||||
#define ASSUAN_Missing_Certificate 203
|
|
||||||
#define ASSUAN_Bad_Signature 204
|
|
||||||
#define ASSUAN_No_Agent 205
|
|
||||||
#define ASSUAN_Agent_Error 206
|
|
||||||
#define ASSUAN_No_Public_Key 207
|
|
||||||
#define ASSUAN_No_Secret_Key 208
|
|
||||||
#define ASSUAN_Invalid_Name 209
|
|
||||||
|
|
||||||
#define ASSUAN_Cert_Revoked 301
|
|
||||||
#define ASSUAN_No_CRL_For_Cert 302
|
|
||||||
#define ASSUAN_CRL_Too_Old 303
|
|
||||||
#define ASSUAN_Not_Trusted 304
|
|
||||||
|
|
||||||
#define ASSUAN_Card_Error 401
|
|
||||||
#define ASSUAN_Invalid_Card 402
|
|
||||||
#define ASSUAN_No_PKCS15_App 403
|
|
||||||
#define ASSUAN_Card_Not_Present 404
|
|
||||||
#define ASSUAN_Invalid_Id 405
|
|
||||||
|
|
||||||
/* Error codes in the range 1000 to 9999 may be used by applications
|
|
||||||
at their own discretion. */
|
|
||||||
#define ASSUAN_USER_ERROR_FIRST 1000
|
|
||||||
#define ASSUAN_USER_ERROR_LAST 9999
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef int assuan_error_t;
|
|
||||||
|
|
||||||
typedef assuan_error_t AssuanError _ASSUAN_DEPRECATED;
|
|
||||||
|
|
||||||
/* This is a list of pre-registered ASSUAN commands */
|
|
||||||
/* Note, these command IDs are now deprectated and solely exists for
|
|
||||||
compatibility reasons. */
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
ASSUAN_CMD_NOP = 0,
|
|
||||||
ASSUAN_CMD_CANCEL, /* cancel the current request */
|
|
||||||
ASSUAN_CMD_BYE,
|
|
||||||
ASSUAN_CMD_AUTH,
|
|
||||||
ASSUAN_CMD_RESET,
|
|
||||||
ASSUAN_CMD_OPTION,
|
|
||||||
ASSUAN_CMD_DATA,
|
|
||||||
ASSUAN_CMD_END,
|
|
||||||
ASSUAN_CMD_INPUT,
|
|
||||||
ASSUAN_CMD_OUTPUT,
|
|
||||||
|
|
||||||
ASSUAN_CMD_USER = 256 /* Other commands should be used with this offset*/
|
|
||||||
} AssuanCommand;
|
|
||||||
|
|
||||||
|
|
||||||
#else /*!_ASSUAN_ONLY_GPG_ERRORS*/
|
|
||||||
|
|
||||||
/* Choose a type compatible with gpg_error_t. */
|
|
||||||
typedef unsigned int assuan_error_t;
|
|
||||||
|
|
||||||
#endif /*!_ASSUAN_ONLY_GPG_ERRORS*/
|
|
||||||
|
|
||||||
|
|
||||||
/* Definitions of flags for assuan_set_flag(). */
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
/* When using a pipe server, by default Assuan will wait for the
|
|
||||||
forked process to die in assuan_disconnect. In certain cases
|
|
||||||
this is not desirable. By setting this flag, the waitpid will
|
|
||||||
be skipped and the caller is responsible to cleanup a forked
|
|
||||||
process. */
|
|
||||||
ASSUAN_NO_WAITPID = 1,
|
|
||||||
/* This flag indicates whether Assuan logging is in confidential
|
|
||||||
mode. Use assuan_{begin,end}_condidential to change the
|
|
||||||
mode. */
|
|
||||||
ASSUAN_CONFIDENTIAL = 2
|
|
||||||
}
|
|
||||||
assuan_flag_t;
|
|
||||||
|
|
||||||
#define ASSUAN_LINELENGTH 1002 /* 1000 + [CR,]LF */
|
|
||||||
|
|
||||||
struct assuan_context_s;
|
|
||||||
typedef struct assuan_context_s *assuan_context_t;
|
|
||||||
#ifndef _ASSUAN_ONLY_GPG_ERRORS
|
|
||||||
typedef struct assuan_context_s *ASSUAN_CONTEXT _ASSUAN_DEPRECATED;
|
|
||||||
#endif /*_ASSUAN_ONLY_GPG_ERRORS*/
|
|
||||||
|
|
||||||
/* Because we use system handles and not libc low level file
|
|
||||||
descriptors on W32, we need to declare them as HANDLE (which
|
|
||||||
actually is a plain pointer). This is required to eventually
|
|
||||||
support 64 bit Windows systems. */
|
|
||||||
#ifdef _WIN32
|
|
||||||
typedef void *assuan_fd_t;
|
|
||||||
#define ASSUAN_INVALID_FD ((void*)(-1))
|
|
||||||
#define ASSUAN_INT2FD(s) ((void *)(s))
|
|
||||||
#define ASSUAN_FD2INT(h) ((unsigned int)(h))
|
|
||||||
#else
|
|
||||||
typedef int assuan_fd_t;
|
|
||||||
#define ASSUAN_INVALID_FD (-1)
|
|
||||||
#define ASSUAN_INT2FD(s) ((s))
|
|
||||||
#define ASSUAN_FD2INT(h) ((h))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* Assuan features an emulation of Unix domain sockets based on a
|
|
||||||
local TCP connections. To implement access permissions based on
|
|
||||||
file permissions a nonce is used which is expected by th server as
|
|
||||||
the first bytes received. This structure is used by the server to
|
|
||||||
save the nonce created initially by bind. On POSIX systems this is
|
|
||||||
a dummy operation. */
|
|
||||||
struct assuan_sock_nonce_s
|
|
||||||
{
|
|
||||||
size_t length;
|
|
||||||
#ifdef _WIN32
|
|
||||||
char nonce[16];
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
typedef struct assuan_sock_nonce_s assuan_sock_nonce_t;
|
|
||||||
|
|
||||||
/* Define the Unix domain socket structure for Windows. */
|
|
||||||
#if defined(_WIN32) && !defined(_ASSUAN_NO_SOCKET_WRAPPER)
|
|
||||||
#ifndef AF_LOCAL
|
|
||||||
#define AF_LOCAL AF_UNIX
|
|
||||||
#endif
|
|
||||||
#define EADDRINUSE WSAEADDRINUSE
|
|
||||||
struct sockaddr_un
|
|
||||||
{
|
|
||||||
short sun_family;
|
|
||||||
unsigned short sun_port;
|
|
||||||
struct in_addr sun_addr;
|
|
||||||
char sun_path[108-2-4];
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* Definition of hook functions used to conditionally replace the
|
|
||||||
default I/O functions. */
|
|
||||||
struct assuan_io_hooks
|
|
||||||
{
|
|
||||||
int (*read_hook)(assuan_context_t, assuan_fd_t, void *, size_t, ssize_t *);
|
|
||||||
int (*write_hook)(assuan_context_t, assuan_fd_t fd,
|
|
||||||
const void *, size_t, ssize_t *);
|
|
||||||
};
|
|
||||||
typedef struct assuan_io_hooks *assuan_io_hooks_t;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-- assuan-handler.c --*/
|
|
||||||
int assuan_register_command (assuan_context_t ctx,
|
|
||||||
const char *cmd_string,
|
|
||||||
int (*handler)(assuan_context_t, char *));
|
|
||||||
int assuan_register_post_cmd_notify (assuan_context_t ctx,
|
|
||||||
void (*fnc)(assuan_context_t, int));
|
|
||||||
int assuan_register_bye_notify (assuan_context_t ctx,
|
|
||||||
void (*fnc)(assuan_context_t));
|
|
||||||
int assuan_register_reset_notify (assuan_context_t ctx,
|
|
||||||
void (*fnc)(assuan_context_t));
|
|
||||||
int assuan_register_cancel_notify (assuan_context_t ctx,
|
|
||||||
void (*fnc)(assuan_context_t));
|
|
||||||
int assuan_register_input_notify (assuan_context_t ctx,
|
|
||||||
void (*fnc)(assuan_context_t, const char *));
|
|
||||||
int assuan_register_output_notify (assuan_context_t ctx,
|
|
||||||
void (*fnc)(assuan_context_t, const char *));
|
|
||||||
|
|
||||||
int assuan_register_option_handler (assuan_context_t ctx,
|
|
||||||
int (*fnc)(assuan_context_t,
|
|
||||||
const char*, const char*));
|
|
||||||
|
|
||||||
int assuan_process (assuan_context_t ctx);
|
|
||||||
int assuan_process_next (assuan_context_t ctx);
|
|
||||||
int assuan_process_done (assuan_context_t ctx, int rc);
|
|
||||||
int assuan_get_active_fds (assuan_context_t ctx, int what,
|
|
||||||
assuan_fd_t *fdarray, int fdarraysize);
|
|
||||||
|
|
||||||
|
|
||||||
FILE *assuan_get_data_fp (assuan_context_t ctx);
|
|
||||||
assuan_error_t assuan_set_okay_line (assuan_context_t ctx, const char *line);
|
|
||||||
assuan_error_t assuan_write_status (assuan_context_t ctx,
|
|
||||||
const char *keyword, const char *text);
|
|
||||||
|
|
||||||
/* Negotiate a file descriptor. If LINE contains "FD=N", returns N
|
|
||||||
assuming a local file descriptor. If LINE contains "FD" reads a
|
|
||||||
file descriptor via CTX and stores it in *RDF (the CTX must be
|
|
||||||
capable of passing file descriptors). Under W32 the returned FD is
|
|
||||||
a libc-type one. */
|
|
||||||
assuan_error_t assuan_command_parse_fd (assuan_context_t ctx, char *line,
|
|
||||||
assuan_fd_t *rfd);
|
|
||||||
|
|
||||||
|
|
||||||
/*-- assuan-listen.c --*/
|
|
||||||
assuan_error_t assuan_set_hello_line (assuan_context_t ctx, const char *line);
|
|
||||||
assuan_error_t assuan_accept (assuan_context_t ctx);
|
|
||||||
assuan_fd_t assuan_get_input_fd (assuan_context_t ctx);
|
|
||||||
assuan_fd_t assuan_get_output_fd (assuan_context_t ctx);
|
|
||||||
assuan_error_t assuan_close_input_fd (assuan_context_t ctx);
|
|
||||||
assuan_error_t assuan_close_output_fd (assuan_context_t ctx);
|
|
||||||
|
|
||||||
|
|
||||||
/*-- assuan-pipe-server.c --*/
|
|
||||||
int assuan_init_pipe_server (assuan_context_t *r_ctx, int filedes[2]);
|
|
||||||
void assuan_deinit_server (assuan_context_t ctx);
|
|
||||||
|
|
||||||
/*-- assuan-socket-server.c --*/
|
|
||||||
int assuan_init_socket_server (assuan_context_t *r_ctx, assuan_fd_t listen_fd);
|
|
||||||
int assuan_init_connected_socket_server (assuan_context_t *r_ctx,
|
|
||||||
assuan_fd_t fd) _ASSUAN_DEPRECATED;
|
|
||||||
int assuan_init_socket_server_ext (assuan_context_t *r_ctx, assuan_fd_t fd,
|
|
||||||
unsigned int flags);
|
|
||||||
void assuan_set_sock_nonce (assuan_context_t ctx, assuan_sock_nonce_t *nonce);
|
|
||||||
|
|
||||||
/*-- assuan-pipe-connect.c --*/
|
|
||||||
assuan_error_t assuan_pipe_connect (assuan_context_t *ctx,
|
|
||||||
const char *name,
|
|
||||||
const char *const argv[],
|
|
||||||
int *fd_child_list);
|
|
||||||
assuan_error_t assuan_pipe_connect2 (assuan_context_t *ctx,
|
|
||||||
const char *name,
|
|
||||||
const char *const argv[],
|
|
||||||
int *fd_child_list,
|
|
||||||
void (*atfork) (void*, int),
|
|
||||||
void *atforkvalue) _ASSUAN_DEPRECATED;
|
|
||||||
assuan_error_t assuan_pipe_connect_ext (assuan_context_t *ctx,
|
|
||||||
const char *name,
|
|
||||||
const char *const argv[],
|
|
||||||
int *fd_child_list,
|
|
||||||
void (*atfork) (void *, int),
|
|
||||||
void *atforkvalue,
|
|
||||||
unsigned int flags);
|
|
||||||
|
|
||||||
/*-- assuan-socket-connect.c --*/
|
|
||||||
assuan_error_t assuan_socket_connect (assuan_context_t *ctx,
|
|
||||||
const char *name,
|
|
||||||
pid_t server_pid);
|
|
||||||
assuan_error_t assuan_socket_connect_ext (assuan_context_t *ctx,
|
|
||||||
const char *name,
|
|
||||||
pid_t server_pid,
|
|
||||||
unsigned int flags);
|
|
||||||
|
|
||||||
/*-- assuan-connect.c --*/
|
|
||||||
void assuan_disconnect (assuan_context_t ctx);
|
|
||||||
pid_t assuan_get_pid (assuan_context_t ctx);
|
|
||||||
#ifndef _WIN32
|
|
||||||
assuan_error_t assuan_get_peercred (assuan_context_t ctx,
|
|
||||||
pid_t *pid, uid_t *uid, gid_t *gid);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*-- assuan-client.c --*/
|
|
||||||
assuan_error_t
|
|
||||||
assuan_transact (assuan_context_t ctx,
|
|
||||||
const char *command,
|
|
||||||
assuan_error_t (*data_cb)(void *, const void *, size_t),
|
|
||||||
void *data_cb_arg,
|
|
||||||
assuan_error_t (*inquire_cb)(void*, const char *),
|
|
||||||
void *inquire_cb_arg,
|
|
||||||
assuan_error_t (*status_cb)(void*, const char *),
|
|
||||||
void *status_cb_arg);
|
|
||||||
|
|
||||||
|
|
||||||
/*-- assuan-inquire.c --*/
|
|
||||||
assuan_error_t assuan_inquire (assuan_context_t ctx, const char *keyword,
|
|
||||||
unsigned char **r_buffer, size_t *r_length,
|
|
||||||
size_t maxlen);
|
|
||||||
assuan_error_t assuan_inquire_ext (assuan_context_t ctx, const char *keyword,
|
|
||||||
size_t maxlen,
|
|
||||||
int (*cb) (void *cb_data, int rc,
|
|
||||||
unsigned char *buf,
|
|
||||||
size_t buf_len),
|
|
||||||
void *cb_data);
|
|
||||||
/*-- assuan-buffer.c --*/
|
|
||||||
assuan_error_t assuan_read_line (assuan_context_t ctx,
|
|
||||||
char **line, size_t *linelen);
|
|
||||||
int assuan_pending_line (assuan_context_t ctx);
|
|
||||||
assuan_error_t assuan_write_line (assuan_context_t ctx, const char *line );
|
|
||||||
assuan_error_t assuan_send_data (assuan_context_t ctx,
|
|
||||||
const void *buffer, size_t length);
|
|
||||||
|
|
||||||
/* The file descriptor must be pending before assuan_receivefd is
|
|
||||||
called. This means that assuan_sendfd should be called *before* the
|
|
||||||
trigger is sent (normally via assuan_write_line ("INPUT FD")). */
|
|
||||||
assuan_error_t assuan_sendfd (assuan_context_t ctx, assuan_fd_t fd);
|
|
||||||
assuan_error_t assuan_receivefd (assuan_context_t ctx, assuan_fd_t *fd);
|
|
||||||
|
|
||||||
|
|
||||||
/*-- assuan-util.c --*/
|
|
||||||
void assuan_set_malloc_hooks ( void *(*new_alloc_func)(size_t n),
|
|
||||||
void *(*new_realloc_func)(void *p, size_t n),
|
|
||||||
void (*new_free_func)(void*) );
|
|
||||||
void assuan_set_io_hooks (assuan_io_hooks_t io_hooks);
|
|
||||||
void assuan_set_log_stream (assuan_context_t ctx, FILE *fp);
|
|
||||||
int assuan_set_error (assuan_context_t ctx, int err, const char *text);
|
|
||||||
void assuan_set_pointer (assuan_context_t ctx, void *pointer);
|
|
||||||
void *assuan_get_pointer (assuan_context_t ctx);
|
|
||||||
|
|
||||||
void assuan_begin_confidential (assuan_context_t ctx);
|
|
||||||
void assuan_end_confidential (assuan_context_t ctx);
|
|
||||||
|
|
||||||
void assuan_set_io_monitor (assuan_context_t ctx,
|
|
||||||
unsigned int (*monitor)(assuan_context_t ctx,
|
|
||||||
int direction,
|
|
||||||
const char *line,
|
|
||||||
size_t linelen));
|
|
||||||
|
|
||||||
/* For context CTX, set the flag FLAG to VALUE. Values for flags
|
|
||||||
are usually 1 or 0 but certain flags might allow for other values;
|
|
||||||
see the description of the type assuan_flag_t for details. */
|
|
||||||
void assuan_set_flag (assuan_context_t ctx, assuan_flag_t flag, int value);
|
|
||||||
|
|
||||||
/* Return the VALUE of FLAG in context CTX. */
|
|
||||||
int assuan_get_flag (assuan_context_t ctx, assuan_flag_t flag);
|
|
||||||
|
|
||||||
|
|
||||||
/*-- assuan-errors.c --*/
|
|
||||||
|
|
||||||
#ifndef _ASSUAN_ONLY_GPG_ERRORS
|
|
||||||
/* Return a string describing the assuan error. The use of this
|
|
||||||
function is deprecated; it is better to call
|
|
||||||
assuan_set_assuan_err_source once and then make use libgpg-error. */
|
|
||||||
const char *assuan_strerror (assuan_error_t err);
|
|
||||||
#endif /*_ASSUAN_ONLY_GPG_ERRORS*/
|
|
||||||
|
|
||||||
/* Enable gpg-error style error codes. ERRSOURCE is one of gpg-error
|
|
||||||
sources. Note, that this function is not thread-safe and should be
|
|
||||||
used right at startup. Switching back to the old style mode is not
|
|
||||||
supported. */
|
|
||||||
void assuan_set_assuan_err_source (int errsource);
|
|
||||||
|
|
||||||
/*-- assuan-logging.c --*/
|
|
||||||
|
|
||||||
/* Set the stream to which assuan should log message not associated
|
|
||||||
with a context. By default, this is stderr. The default value
|
|
||||||
will be changed when the first log stream is associated with a
|
|
||||||
context. Note, that this function is not thread-safe and should
|
|
||||||
in general be used right at startup. */
|
|
||||||
extern void assuan_set_assuan_log_stream (FILE *fp);
|
|
||||||
|
|
||||||
/* Return the stream which is currently being using for global logging. */
|
|
||||||
extern FILE *assuan_get_assuan_log_stream (void);
|
|
||||||
|
|
||||||
/* Set the prefix to be used at the start of a line emitted by assuan
|
|
||||||
on the log stream. The default is the empty string. Note, that
|
|
||||||
this function is not thread-safe and should in general be used
|
|
||||||
right at startup. */
|
|
||||||
void assuan_set_assuan_log_prefix (const char *text);
|
|
||||||
|
|
||||||
/* Return a prefix to be used at the start of a line emitted by assuan
|
|
||||||
on the log stream. The default implementation returns the empty
|
|
||||||
string, i.e. "" */
|
|
||||||
const char *assuan_get_assuan_log_prefix (void);
|
|
||||||
|
|
||||||
|
|
||||||
/*-- assuan-socket.c --*/
|
|
||||||
|
|
||||||
/* These are socket wrapper functions to support an emulation of Unix
|
|
||||||
domain sockets on Windows W32. */
|
|
||||||
int assuan_sock_close (assuan_fd_t fd);
|
|
||||||
assuan_fd_t assuan_sock_new (int domain, int type, int proto);
|
|
||||||
int assuan_sock_connect (assuan_fd_t sockfd,
|
|
||||||
struct sockaddr *addr, int addrlen);
|
|
||||||
int assuan_sock_bind (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen);
|
|
||||||
int assuan_sock_get_nonce (struct sockaddr *addr, int addrlen,
|
|
||||||
assuan_sock_nonce_t *nonce);
|
|
||||||
int assuan_sock_check_nonce (assuan_fd_t fd, assuan_sock_nonce_t *nonce);
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif /* ASSUAN_H */
|
|
257
assuan/mkerrors
257
assuan/mkerrors
@ -1,257 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
# mkerrors - Extract error strings from assuan.h
|
|
||||||
# and create C source for assuan_strerror
|
|
||||||
# Copyright (C) 2001, 2002, 2006 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 <http://www.gnu.org/licenses/>.
|
|
||||||
cat <<EOF
|
|
||||||
/* Generated automatically by mkerrors */
|
|
||||||
/* Do not edit! See mkerrors for copyright notice. */
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include <config.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#undef _ASSUAN_IN_LIBASSUAN /* undef to get all error codes. */
|
|
||||||
#include "assuan.h"
|
|
||||||
#include "assuan-defs.h"
|
|
||||||
|
|
||||||
/* If true the modern gpg-error style error codes are used in the
|
|
||||||
API. */
|
|
||||||
static unsigned int err_source;
|
|
||||||
|
|
||||||
/* Enable gpg-error style error codes. ERRSOURCE is one of gpg-error
|
|
||||||
sources. Note, that this function is not thread-safe and should be
|
|
||||||
used right at startup. Switching back to the old style mode is not
|
|
||||||
supported. */
|
|
||||||
void
|
|
||||||
assuan_set_assuan_err_source (int errsource)
|
|
||||||
{
|
|
||||||
errsource &= 0xff;
|
|
||||||
err_source = errsource? errsource : 31 /*GPG_ERR_SOURCE_ANY*/;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Helper to map old style Assuan error codes to gpg-error codes.
|
|
||||||
This is used internally to keep an compatible ABI. */
|
|
||||||
assuan_error_t
|
|
||||||
_assuan_error (int oldcode)
|
|
||||||
{
|
|
||||||
unsigned int n;
|
|
||||||
|
|
||||||
if (!err_source)
|
|
||||||
{
|
|
||||||
if (oldcode == -1)
|
|
||||||
return -1;
|
|
||||||
else
|
|
||||||
return (oldcode & 0x00ffffff); /* Make sure that the gpg-error
|
|
||||||
source part is cleared. */
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (oldcode)
|
|
||||||
{
|
|
||||||
case ASSUAN_General_Error: n = 257; break;
|
|
||||||
case ASSUAN_Accept_Failed: n = 258; break;
|
|
||||||
case ASSUAN_Connect_Failed: n = 259; break;
|
|
||||||
case ASSUAN_Invalid_Response: n = 260; break;
|
|
||||||
case ASSUAN_Invalid_Value: n = 261; break;
|
|
||||||
case ASSUAN_Line_Not_Terminated: n = 262; break;
|
|
||||||
case ASSUAN_Line_Too_Long: n = 263; break;
|
|
||||||
case ASSUAN_Nested_Commands: n = 264; break;
|
|
||||||
case ASSUAN_No_Data_Callback: n = 265; break;
|
|
||||||
case ASSUAN_No_Inquire_Callback: n = 266; break;
|
|
||||||
case ASSUAN_Not_A_Server: n = 267; break;
|
|
||||||
case ASSUAN_Not_Implemented: n = 69; break;
|
|
||||||
case ASSUAN_Parameter_Conflict: n = 280; break;
|
|
||||||
case ASSUAN_Problem_Starting_Server: n = 269; break;
|
|
||||||
case ASSUAN_Server_Fault: n = 80; break;
|
|
||||||
case ASSUAN_Syntax_Error: n = 276; break;
|
|
||||||
case ASSUAN_Too_Much_Data: n = 273; break;
|
|
||||||
case ASSUAN_Unexpected_Command: n = 274; break;
|
|
||||||
case ASSUAN_Unknown_Command: n = 275; break;
|
|
||||||
case ASSUAN_Canceled: n = 277; break;
|
|
||||||
case ASSUAN_No_Secret_Key: n = 17; break;
|
|
||||||
case ASSUAN_Not_Confirmed: n = 114; break;
|
|
||||||
|
|
||||||
case ASSUAN_Read_Error:
|
|
||||||
switch (errno)
|
|
||||||
{
|
|
||||||
case 0: n = 16381; /*GPG_ERR_MISSING_ERRNO*/ break;
|
|
||||||
case EAGAIN:
|
|
||||||
n = (6 | (1 << 15));
|
|
||||||
break;
|
|
||||||
default: n = 270; /*GPG_ERR_ASS_READ_ERROR*/ break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ASSUAN_Write_Error:
|
|
||||||
switch (errno)
|
|
||||||
{
|
|
||||||
case 0: n = 16381; /*GPG_ERR_MISSING_ERRNO*/ break;
|
|
||||||
case EAGAIN:
|
|
||||||
n = (6 | (1 << 15));
|
|
||||||
break;
|
|
||||||
default: n = 271; /*GPG_ERR_ASS_WRITE_ERROR*/ break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ASSUAN_Out_Of_Core:
|
|
||||||
switch (errno)
|
|
||||||
{
|
|
||||||
case 0: /* Should not happen but a user might have provided
|
|
||||||
an incomplete implemented malloc function. Give
|
|
||||||
him a chance to correct this fault but make sure
|
|
||||||
an error is indeed returned. */
|
|
||||||
n = 16381; /*GPG_ERR_MISSING_ERRNO*/
|
|
||||||
break;
|
|
||||||
case ENOMEM:
|
|
||||||
n = (86 | (1 << 15));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
n = 16382; /*GPG_ERR_UNKNOWN_ERRNO*/
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case -1: n = 16383 /*GPG_ERR_EOF*/; break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
n = 257;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ((err_source << 24) | (n & 0x00ffffff));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* A small helper function to treat EAGAIN transparently to the
|
|
||||||
caller. */
|
|
||||||
int
|
|
||||||
_assuan_error_is_eagain (assuan_error_t err)
|
|
||||||
{
|
|
||||||
if ((!err_source && err == ASSUAN_Read_Error && errno == EAGAIN)
|
|
||||||
|| (err_source && (err & ((1 << 24) - 1)) == (6 | (1 << 15))))
|
|
||||||
{
|
|
||||||
/* Avoid spinning by sleeping for one tenth of a second. */
|
|
||||||
_assuan_usleep (100000);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* assuan_strerror:
|
|
||||||
* @err: Error code
|
|
||||||
*
|
|
||||||
* This function returns a textual representaion of the given
|
|
||||||
* errorcode. If this is an unknown value, a string with the value
|
|
||||||
* is returned (Beware: it is hold in a static buffer).
|
|
||||||
*
|
|
||||||
* Return value: String with the error description.
|
|
||||||
**/
|
|
||||||
const char *
|
|
||||||
assuan_strerror (assuan_error_t err)
|
|
||||||
{
|
|
||||||
const char *s;
|
|
||||||
static char buf[50];
|
|
||||||
|
|
||||||
switch (err)
|
|
||||||
{
|
|
||||||
EOF
|
|
||||||
|
|
||||||
awk '
|
|
||||||
/ASSUAN_No_Error/ { okay=1 }
|
|
||||||
!okay {next}
|
|
||||||
/^#define[ ]+ASSUAN_[A-Za-z_]*/ { print_code($2) }
|
|
||||||
/ASSUAN_USER_ERROR_LAST/ { exit 0 }
|
|
||||||
|
|
||||||
|
|
||||||
function print_code( s )
|
|
||||||
{
|
|
||||||
printf " case %s: s=\"", s ;
|
|
||||||
gsub(/_/, " ", s );
|
|
||||||
printf "%s\"; break;\n", tolower(substr(s,8));
|
|
||||||
}
|
|
||||||
'
|
|
||||||
|
|
||||||
cat <<EOF
|
|
||||||
case -1: s = "EOF (-1)"; break;
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
unsigned int source, code, n;
|
|
||||||
|
|
||||||
source = ((err >> 24) & 0xff);
|
|
||||||
code = (err & 0x00ffffff);
|
|
||||||
if (source)
|
|
||||||
{
|
|
||||||
/* Assume this is an libgpg-error and try to map the codes
|
|
||||||
back. */
|
|
||||||
switch (code)
|
|
||||||
{
|
|
||||||
case 257: n = ASSUAN_General_Error ; break;
|
|
||||||
case 258: n = ASSUAN_Accept_Failed ; break;
|
|
||||||
case 259: n = ASSUAN_Connect_Failed ; break;
|
|
||||||
case 260: n = ASSUAN_Invalid_Response ; break;
|
|
||||||
case 261: n = ASSUAN_Invalid_Value ; break;
|
|
||||||
case 262: n = ASSUAN_Line_Not_Terminated ; break;
|
|
||||||
case 263: n = ASSUAN_Line_Too_Long ; break;
|
|
||||||
case 264: n = ASSUAN_Nested_Commands ; break;
|
|
||||||
case 265: n = ASSUAN_No_Data_Callback ; break;
|
|
||||||
case 266: n = ASSUAN_No_Inquire_Callback ; break;
|
|
||||||
case 267: n = ASSUAN_Not_A_Server ; break;
|
|
||||||
case 69: n = ASSUAN_Not_Implemented ; break;
|
|
||||||
case 280: n = ASSUAN_Parameter_Conflict ; break;
|
|
||||||
case 269: n = ASSUAN_Problem_Starting_Server; break;
|
|
||||||
case 270: n = ASSUAN_Read_Error ; break;
|
|
||||||
case 271: n = ASSUAN_Write_Error ; break;
|
|
||||||
case 80: n = ASSUAN_Server_Fault ; break;
|
|
||||||
case 276: n = ASSUAN_Syntax_Error ; break;
|
|
||||||
case 273: n = ASSUAN_Too_Much_Data ; break;
|
|
||||||
case 274: n = ASSUAN_Unexpected_Command ; break;
|
|
||||||
case 275: n = ASSUAN_Unknown_Command ; break;
|
|
||||||
case 277: n = ASSUAN_Canceled ; break;
|
|
||||||
case 114: n = ASSUAN_Not_Confirmed ; break;
|
|
||||||
case ((1<<15)|86): n = ASSUAN_Out_Of_Core ; break;
|
|
||||||
default: n = 0; break;
|
|
||||||
}
|
|
||||||
if (n)
|
|
||||||
s = assuan_strerror (n);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sprintf (buf, "ec=%u.%u", source, code );
|
|
||||||
s=buf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sprintf (buf, "ec=%d", err );
|
|
||||||
s=buf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
EOF
|
|
85
configure.ac
85
configure.ac
@ -188,8 +188,10 @@ AM_CONDITIONAL(HAVE_PTH, test "$have_pth" = "yes")
|
|||||||
AM_CONDITIONAL(HAVE_PTHREAD, test "$have_pthread" = "yes")
|
AM_CONDITIONAL(HAVE_PTHREAD, test "$have_pthread" = "yes")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Checks for header files.
|
# Checks for header files.
|
||||||
AC_CHECK_HEADERS(sys/select.h)
|
AC_CHECK_HEADERS(sys/select.h)
|
||||||
|
AC_CHECK_HEADERS([sys/uio.h])
|
||||||
|
|
||||||
|
|
||||||
# Type checks.
|
# Type checks.
|
||||||
@ -219,13 +221,6 @@ if test "$GCC" = yes; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Network library fun.
|
|
||||||
AC_CHECK_FUNC(gethostbyname, , AC_CHECK_LIB(nsl, gethostbyname,
|
|
||||||
[NETLIBS="-lnsl $NETLIBS"]))
|
|
||||||
AC_CHECK_FUNC(setsockopt, , AC_CHECK_LIB(socket, setsockopt,
|
|
||||||
[NETLIBS="-lsocket $NETLIBS"]))
|
|
||||||
AC_SUBST(NETLIBS)
|
|
||||||
|
|
||||||
# Checks for library functions.
|
# Checks for library functions.
|
||||||
AC_FUNC_FSEEKO
|
AC_FUNC_FSEEKO
|
||||||
|
|
||||||
@ -277,7 +272,15 @@ AM_PATH_GPG_ERROR(1.4,, AC_MSG_ERROR([libgpg-error was not found]))
|
|||||||
AC_DEFINE(GPG_ERR_SOURCE_DEFAULT, GPG_ERR_SOURCE_GPGME,
|
AC_DEFINE(GPG_ERR_SOURCE_DEFAULT, GPG_ERR_SOURCE_GPGME,
|
||||||
[The default error source for GPGME.])
|
[The default error source for GPGME.])
|
||||||
|
|
||||||
|
# And for libassuan.
|
||||||
|
NEED_LIBASSUAN_VERSION=1.1.0
|
||||||
|
have_libassuan=no
|
||||||
|
AM_PATH_LIBASSUAN("$NEED_LIBASSUAN_VERSION",
|
||||||
|
have_libassuan=yes, have_libassuan=no)
|
||||||
|
AM_CONDITIONAL(HAVE_ASSUAN, test "$have_libassuan" = "yes")
|
||||||
|
if test "$have_libassuan" = "yes"; then
|
||||||
|
AC_DEFINE(ENABLE_ASSUAN,1,[Whether Assuan support is enabled])
|
||||||
|
fi
|
||||||
|
|
||||||
# Checks for system services
|
# Checks for system services
|
||||||
NEED_GPG_VERSION_DEFAULT=1.3.0
|
NEED_GPG_VERSION_DEFAULT=1.3.0
|
||||||
@ -510,6 +513,12 @@ AC_ARG_ENABLE(gpgsm-test,
|
|||||||
run_gpgsm_test=$enableval)
|
run_gpgsm_test=$enableval)
|
||||||
AM_CONDITIONAL(RUN_GPGSM_TESTS, test "$run_gpgsm_test" = "yes")
|
AM_CONDITIONAL(RUN_GPGSM_TESTS, test "$run_gpgsm_test" = "yes")
|
||||||
|
|
||||||
|
# Require libassuan if GPGSM is here.
|
||||||
|
require_libassuan=no
|
||||||
|
if test "$GPGSM" != "no"; then
|
||||||
|
require_libassuan=yes
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
NO_OVERRIDE=no
|
NO_OVERRIDE=no
|
||||||
AC_ARG_WITH(gpgconf,
|
AC_ARG_WITH(gpgconf,
|
||||||
@ -614,13 +623,6 @@ if test "$GPGCONF" != "no"; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
# FIXME: Only build if supported.
|
|
||||||
AM_CONDITIONAL(BUILD_ASSUAN, test "$GPGSM" != "no")
|
|
||||||
if test "$GPGSM" != "no"; then
|
|
||||||
AC_DEFINE(HAVE_ASSUAN_H, 1,
|
|
||||||
[Defined if we are building with assuan support.])
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check for funopen
|
# Check for funopen
|
||||||
AC_CHECK_FUNCS(funopen)
|
AC_CHECK_FUNCS(funopen)
|
||||||
if test $ac_cv_func_funopen != yes; then
|
if test $ac_cv_func_funopen != yes; then
|
||||||
@ -636,18 +638,12 @@ if test $ac_cv_func_funopen != yes; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# More assuan replacement functions.
|
# Replacement functions.
|
||||||
AC_REPLACE_FUNCS(isascii)
|
|
||||||
AC_REPLACE_FUNCS(putc_unlocked)
|
|
||||||
AC_REPLACE_FUNCS(memrchr)
|
|
||||||
AC_REPLACE_FUNCS(stpcpy)
|
AC_REPLACE_FUNCS(stpcpy)
|
||||||
# Check for unistd.h for setenv replacement function.
|
# Check for unistd.h for setenv replacement function.
|
||||||
AC_CHECK_HEADERS(unistd.h)
|
AC_CHECK_HEADERS(unistd.h)
|
||||||
AC_REPLACE_FUNCS(setenv)
|
AC_REPLACE_FUNCS(setenv)
|
||||||
|
|
||||||
# More assuan checks.
|
|
||||||
AC_CHECK_HEADERS([sys/uio.h])
|
|
||||||
|
|
||||||
# Assuan check for descriptor passing.
|
# Assuan check for descriptor passing.
|
||||||
AC_CHECK_MEMBER(struct cmsghdr.cmsg_len,
|
AC_CHECK_MEMBER(struct cmsghdr.cmsg_len,
|
||||||
[supports_descriptor_passing=yes],
|
[supports_descriptor_passing=yes],
|
||||||
@ -684,27 +680,6 @@ fi
|
|||||||
|
|
||||||
AM_CONDITIONAL(USE_DESCRIPTOR_PASSING, test "$use_descriptor_passing" = "yes")
|
AM_CONDITIONAL(USE_DESCRIPTOR_PASSING, test "$use_descriptor_passing" = "yes")
|
||||||
|
|
||||||
# Assuan check for the getsockopt SO_PEERCRED
|
|
||||||
AC_MSG_CHECKING(for SO_PEERCRED)
|
|
||||||
AC_CACHE_VAL(assuan_cv_sys_so_peercred,
|
|
||||||
[AC_TRY_COMPILE([#include <sys/socket.h>],
|
|
||||||
[struct ucred cr;
|
|
||||||
int cl = sizeof cr;
|
|
||||||
getsockopt (1, SOL_SOCKET, SO_PEERCRED, &cr, &cl);],
|
|
||||||
assuan_cv_sys_so_peercred=yes,
|
|
||||||
assuan_cv_sys_so_peercred=no)
|
|
||||||
])
|
|
||||||
AC_MSG_RESULT($assuan_cv_sys_so_peercred)
|
|
||||||
if test $assuan_cv_sys_so_peercred = yes; then
|
|
||||||
AC_DEFINE(HAVE_SO_PEERCRED, 1,
|
|
||||||
[Defined if SO_PEERCRED is supported (Linux specific)])
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "$have_w32_system" = yes; then
|
|
||||||
NETLIBS="-lws2_32 $NETLIBS"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# End of assuan checks.
|
|
||||||
|
|
||||||
AM_CONDITIONAL(BUILD_COMPLUS, test "$component_system" = "COM+")
|
AM_CONDITIONAL(BUILD_COMPLUS, test "$component_system" = "COM+")
|
||||||
|
|
||||||
@ -753,6 +728,28 @@ LTLIBOBJS=`echo "$LIB@&t@OBJS" |
|
|||||||
sed 's,\.[[^.]]* ,.lo ,g;s,\.[[^.]]*$,.lo,'`
|
sed 's,\.[[^.]]* ,.lo ,g;s,\.[[^.]]*$,.lo,'`
|
||||||
AC_SUBST(LTLIBOBJS)
|
AC_SUBST(LTLIBOBJS)
|
||||||
|
|
||||||
|
# Last check.
|
||||||
|
die=no
|
||||||
|
if test "$require_libassuan" = "no"; then
|
||||||
|
die=yes
|
||||||
|
AC_MSG_NOTICE([[
|
||||||
|
***
|
||||||
|
*** You need libassuan to build this program with GPGSM support.
|
||||||
|
*** This library is for example available at
|
||||||
|
*** ftp://ftp.gnupg.org/pub/gcrypt/alpha/libassuan/
|
||||||
|
*** (at least version $NEED_LIBASSUAN_VERSION is required).
|
||||||
|
***]])
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "$die" = "yes"; then
|
||||||
|
AC_MSG_ERROR([[
|
||||||
|
***
|
||||||
|
*** Required libraries not found. Please consult the above messages
|
||||||
|
*** and install them before running configure again.
|
||||||
|
***]])
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Create config files
|
# Create config files
|
||||||
|
|
||||||
@ -780,6 +777,8 @@ echo "
|
|||||||
GpgConf path: $GPGCONF
|
GpgConf path: $GPGCONF
|
||||||
GpgConf version: $GPGCONF_VERSION, min. $NEED_GPGCONF_VERSION
|
GpgConf version: $GPGCONF_VERSION, min. $NEED_GPGCONF_VERSION
|
||||||
|
|
||||||
|
Assuan version: $LIBASSUAN_VERSION
|
||||||
|
|
||||||
GPGME Pthread: $have_pthread
|
GPGME Pthread: $have_pthread
|
||||||
GPGME Pth: $have_pth
|
GPGME Pth: $have_pth
|
||||||
"
|
"
|
||||||
|
79
m4/libassuan.m4
Normal file
79
m4/libassuan.m4
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
dnl Autoconf macros for libassuan
|
||||||
|
dnl Copyright (C) 2002, 2003 Free Software Foundation, Inc.
|
||||||
|
dnl
|
||||||
|
dnl This file is free software; as a special exception the author gives
|
||||||
|
dnl unlimited permission to copy and/or distribute it, with or without
|
||||||
|
dnl modifications, as long as this notice is preserved.
|
||||||
|
dnl
|
||||||
|
dnl This file is distributed in the hope that it will be useful, but
|
||||||
|
dnl WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
|
||||||
|
dnl implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
|
||||||
|
|
||||||
|
dnl AM_PATH_LIBASSUAN([MINIMUM-VERSION,
|
||||||
|
dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]])
|
||||||
|
dnl Test for libassuan and define LIBASSUAN_CFLAGS and LIBASSUAN_LIBS
|
||||||
|
dnl
|
||||||
|
AC_DEFUN([AM_PATH_LIBASSUAN],
|
||||||
|
[ AC_ARG_WITH(libassuan-prefix,
|
||||||
|
AC_HELP_STRING([--with-libassuan-prefix=PFX],
|
||||||
|
[prefix where LIBASSUAN is installed (optional)]),
|
||||||
|
libassuan_config_prefix="$withval", libassuan_config_prefix="")
|
||||||
|
if test x$libassuan_config_prefix != x ; then
|
||||||
|
libassuan_config_args="$libassuan_config_args --prefix=$libassuan_config_prefix"
|
||||||
|
if test x${LIBASSUAN_CONFIG+set} != xset ; then
|
||||||
|
LIBASSUAN_CONFIG=$libassuan_config_prefix/bin/libassuan-config
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_PATH_PROG(LIBASSUAN_CONFIG, libassuan-config, no)
|
||||||
|
min_libassuan_version=ifelse([$1], ,0.0.1,$1)
|
||||||
|
AC_MSG_CHECKING(for LIBASSUAN - version >= $min_libassuan_version)
|
||||||
|
ok=no
|
||||||
|
if test "$LIBASSUAN_CONFIG" != "no" ; then
|
||||||
|
req_major=`echo $min_libassuan_version | \
|
||||||
|
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'`
|
||||||
|
req_minor=`echo $min_libassuan_version | \
|
||||||
|
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'`
|
||||||
|
req_micro=`echo $min_libassuan_version | \
|
||||||
|
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'`
|
||||||
|
libassuan_config_version=`$LIBASSUAN_CONFIG $libassuan_config_args --version`
|
||||||
|
major=`echo $libassuan_config_version | \
|
||||||
|
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'`
|
||||||
|
minor=`echo $libassuan_config_version | \
|
||||||
|
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'`
|
||||||
|
micro=`echo $libassuan_config_version | \
|
||||||
|
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\3/'`
|
||||||
|
if test "$major" -gt "$req_major"; then
|
||||||
|
ok=yes
|
||||||
|
else
|
||||||
|
if test "$major" -eq "$req_major"; then
|
||||||
|
if test "$minor" -gt "$req_minor"; then
|
||||||
|
ok=yes
|
||||||
|
else
|
||||||
|
if test "$minor" -eq "$req_minor"; then
|
||||||
|
if test "$micro" -ge "$req_micro"; then
|
||||||
|
ok=yes
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if test $ok = yes; then
|
||||||
|
LIBASSUAN_CFLAGS=`$LIBASSUAN_CONFIG $libassuan_config_args --cflags`
|
||||||
|
LIBASSUAN_LIBS=`$LIBASSUAN_CONFIG $libassuan_config_args --libs`
|
||||||
|
LIBASSUAN_VERSION="$LIBASSUAN_CONFIG_VERSION"
|
||||||
|
AC_MSG_RESULT(yes)
|
||||||
|
ifelse([$2], , :, [$2])
|
||||||
|
else
|
||||||
|
LIBASSUAN_CFLAGS=""
|
||||||
|
LIBASSUAN_LIBS=""
|
||||||
|
LIBASSUAN_VERSION=""
|
||||||
|
AC_MSG_RESULT(no)
|
||||||
|
ifelse([$3], , :, [$3])
|
||||||
|
fi
|
||||||
|
AC_SUBST(LIBASSUAN_CFLAGS)
|
||||||
|
AC_SUBST(LIBASSUAN_LIBS)
|
||||||
|
AC_SUBST(LIBASSUAN_VERSION)
|
||||||
|
])
|
@ -1,3 +1,33 @@
|
|||||||
|
2009-10-20 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
|
* Makefile.am (assuan_cppflags, assuan_libobjs): Removed.
|
||||||
|
(gpgsm_components): Move engine-assuan.c to ...
|
||||||
|
(assuan_components): ... this new variable.
|
||||||
|
(main_sources): Add this new variable.
|
||||||
|
(AM_CPPFLAGS): Remove $(assuan_cppflags).
|
||||||
|
(AM_CFLAGS): Add @LIBASSUAN_CFLAGS@.
|
||||||
|
(libgpgme_la_DEPENDENCIES, libgpgme_pth_la_DEPENDENCIES)
|
||||||
|
(libgpgme_glib_la_DEPENDENCIES, libgpgme_qt_la_DEPENDENCIES)
|
||||||
|
(libgpgme_pthread_la_DEPENDENCIES): Remove $(assuan_libobjs).
|
||||||
|
(libgpgme_la_LIBADD, libgpgme_pth_la_LIBADD)
|
||||||
|
(libgpgme_glib_la_LIBADD, libgpgme_qt_la_LIBADD))
|
||||||
|
(libgpgme_pthread_la_LIBADD): Replace $(assuan_libobjs) by
|
||||||
|
@LIBASSUAN_LIBS@.
|
||||||
|
* priv-io.h [!HAVE_W32_SYSTEM]: Declare _gpgme_io_recvmsg,
|
||||||
|
_gpgme_io_sendmsg, _gpgme_io_waitpid.
|
||||||
|
* engine-backend.h: Define with [ENABLE_ASSUAN] instead
|
||||||
|
of [ENABLE_GPGSM].
|
||||||
|
* posix-io.c (_gpgme_io_waitpid): Make non-static.
|
||||||
|
* util.h (ENABLE_ASSUAN): Declar _gpgme_assuan_system_hooks,
|
||||||
|
_gpgme_assuan_malloc_hooks, _gpgme_assuan_log_cb.
|
||||||
|
* engine-gpgsm.c: Don't map assuan error codes. Use
|
||||||
|
assuan_release instead of assuan_disconnect.
|
||||||
|
(map_assuan_error): Remove function.
|
||||||
|
(gpgsm_new): Use new assuan context interface.
|
||||||
|
* engine-assuan.c: Use assuan_release instead of
|
||||||
|
assuan_disconnect.
|
||||||
|
(llass_new): Use new assuan context interface.
|
||||||
|
|
||||||
2009-10-07 <wk@g10code.com>
|
2009-10-07 <wk@g10code.com>
|
||||||
|
|
||||||
* priv-io.h [W32]: Include windows.h instead of sys/socket.h.
|
* priv-io.h [W32]: Include windows.h instead of sys/socket.h.
|
||||||
|
@ -60,14 +60,6 @@ else
|
|||||||
libgpgme_version_script_cmd =
|
libgpgme_version_script_cmd =
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if BUILD_ASSUAN
|
|
||||||
assuan_cppflags = -I$(top_srcdir)/assuan
|
|
||||||
assuan_libobjs = ../assuan/libassuan.la
|
|
||||||
else
|
|
||||||
assuan_cppflags =
|
|
||||||
assuan_libobjs =
|
|
||||||
endif
|
|
||||||
|
|
||||||
if HAVE_DOSISH_SYSTEM
|
if HAVE_DOSISH_SYSTEM
|
||||||
system_components = w32-util.c w32-sema.c
|
system_components = w32-util.c w32-sema.c
|
||||||
system_components_not_extra = w32-io.c
|
system_components_not_extra = w32-io.c
|
||||||
@ -77,11 +69,17 @@ system_components_not_extra =
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
if HAVE_GPGSM
|
if HAVE_GPGSM
|
||||||
gpgsm_components = engine-gpgsm.c engine-assuan.c
|
gpgsm_components = engine-gpgsm.c
|
||||||
else
|
else
|
||||||
gpgsm_components =
|
gpgsm_components =
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if HAVE_ASSUAN
|
||||||
|
assuan_components = assuan-support.c engine-assuan.c
|
||||||
|
else
|
||||||
|
assuan_components =
|
||||||
|
endif
|
||||||
|
|
||||||
if HAVE_GPGCONF
|
if HAVE_GPGCONF
|
||||||
gpgconf_components = engine-gpgconf.c
|
gpgconf_components = engine-gpgconf.c
|
||||||
else
|
else
|
||||||
@ -106,7 +104,8 @@ main_sources = \
|
|||||||
import.c export.c genkey.c delete.c edit.c getauditlog.c \
|
import.c export.c genkey.c delete.c edit.c getauditlog.c \
|
||||||
opassuan.c \
|
opassuan.c \
|
||||||
engine.h engine-backend.h engine.c engine-gpg.c status-table.h \
|
engine.h engine-backend.h engine.c engine-gpg.c status-table.h \
|
||||||
$(gpgsm_components) $(gpgconf_components) gpgconf.c \
|
$(gpgsm_components) $(assuan_components) $(gpgconf_components) \
|
||||||
|
gpgconf.c \
|
||||||
sema.h priv-io.h $(system_components) dirinfo.c \
|
sema.h priv-io.h $(system_components) dirinfo.c \
|
||||||
debug.c debug.h gpgme.c version.c error.c
|
debug.c debug.h gpgme.c version.c error.c
|
||||||
|
|
||||||
@ -136,9 +135,9 @@ 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 = @GPG_ERROR_CFLAGS@ @PTH_CPPFLAGS@ \
|
||||||
@QT4_CORE_CFLAGS@
|
@QT4_CORE_CFLAGS@
|
||||||
AM_CFLAGS = @PTH_CFLAGS@ @GLIB_CFLAGS@ @QT4_CORE_CFLAGS@
|
AM_CFLAGS = @LIBASSUAN_CFLAGS@ @PTH_CFLAGS@ @GLIB_CFLAGS@ @QT4_CORE_CFLAGS@
|
||||||
|
|
||||||
if HAVE_W32_SYSTEM
|
if HAVE_W32_SYSTEM
|
||||||
|
|
||||||
@ -185,33 +184,30 @@ endif
|
|||||||
libgpgme_la_LDFLAGS = $(gpgme_res_ldflag) $(no_undefined) $(export_symbols) \
|
libgpgme_la_LDFLAGS = $(gpgme_res_ldflag) $(no_undefined) $(export_symbols) \
|
||||||
$(libgpgme_version_script_cmd) -version-info \
|
$(libgpgme_version_script_cmd) -version-info \
|
||||||
@LIBGPGME_LT_CURRENT@:@LIBGPGME_LT_REVISION@:@LIBGPGME_LT_AGE@
|
@LIBGPGME_LT_CURRENT@:@LIBGPGME_LT_REVISION@:@LIBGPGME_LT_AGE@
|
||||||
libgpgme_la_DEPENDENCIES = $(assuan_libobjs) \
|
libgpgme_la_DEPENDENCIES = @LTLIBOBJS@ $(srcdir)/libgpgme.vers $(gpgme_deps)
|
||||||
@LTLIBOBJS@ $(srcdir)/libgpgme.vers $(gpgme_deps)
|
libgpgme_la_LIBADD = @LIBASSUAN_LIBS@ @LTLIBOBJS@ \
|
||||||
libgpgme_la_LIBADD = $(assuan_libobjs) @LTLIBOBJS@ \
|
|
||||||
@GPG_ERROR_LIBS@ @NETLIBS@
|
@GPG_ERROR_LIBS@ @NETLIBS@
|
||||||
|
|
||||||
libgpgme_pthread_la_LDFLAGS = $(libgpgme_version_script_cmd) -version-info \
|
libgpgme_pthread_la_LDFLAGS = $(libgpgme_version_script_cmd) -version-info \
|
||||||
@LIBGPGME_LT_CURRENT@:@LIBGPGME_LT_REVISION@:@LIBGPGME_LT_AGE@
|
@LIBGPGME_LT_CURRENT@:@LIBGPGME_LT_REVISION@:@LIBGPGME_LT_AGE@
|
||||||
libgpgme_pthread_la_DEPENDENCIES = $(assuan_libobjs) \
|
libgpgme_pthread_la_DEPENDENCIES = @LTLIBOBJS@ $(srcdir)/libgpgme.vers
|
||||||
@LTLIBOBJS@ $(srcdir)/libgpgme.vers
|
libgpgme_pthread_la_LIBADD = @LIBASSUAN_LIBS@ @LTLIBOBJS@ \
|
||||||
libgpgme_pthread_la_LIBADD = $(assuan_libobjs) @LTLIBOBJS@ \
|
|
||||||
-lpthread @GPG_ERROR_LIBS@ @NETLIBS@
|
-lpthread @GPG_ERROR_LIBS@ @NETLIBS@
|
||||||
|
|
||||||
libgpgme_pth_la_LDFLAGS = @PTH_LDFLAGS@ \
|
libgpgme_pth_la_LDFLAGS = @PTH_LDFLAGS@ \
|
||||||
$(libgpgme_version_script_cmd) -version-info \
|
$(libgpgme_version_script_cmd) -version-info \
|
||||||
@LIBGPGME_LT_CURRENT@:@LIBGPGME_LT_REVISION@:@LIBGPGME_LT_AGE@
|
@LIBGPGME_LT_CURRENT@:@LIBGPGME_LT_REVISION@:@LIBGPGME_LT_AGE@
|
||||||
libgpgme_pth_la_DEPENDENCIES = $(assuan_libobjs) \
|
libgpgme_pth_la_DEPENDENCIES = @LTLIBOBJS@ $(srcdir)/libgpgme.vers
|
||||||
@LTLIBOBJS@ $(srcdir)/libgpgme.vers
|
libgpgme_pth_la_LIBADD = @LIBASSUAN_LIBS@ @LTLIBOBJS@ \
|
||||||
libgpgme_pth_la_LIBADD = $(assuan_libobjs) @LTLIBOBJS@ \
|
|
||||||
@PTH_LIBS@ @GPG_ERROR_LIBS@ @NETLIBS@
|
@PTH_LIBS@ @GPG_ERROR_LIBS@ @NETLIBS@
|
||||||
|
|
||||||
if BUILD_W32_GLIB
|
if BUILD_W32_GLIB
|
||||||
libgpgme_glib_la_LDFLAGS = $(gpgme_res_ldflag) $(no_undefined) \
|
libgpgme_glib_la_LDFLAGS = $(gpgme_res_ldflag) $(no_undefined) \
|
||||||
$(export_symbols) $(libgpgme_version_script_cmd) -version-info \
|
$(export_symbols) $(libgpgme_version_script_cmd) -version-info \
|
||||||
@LIBGPGME_LT_CURRENT@:@LIBGPGME_LT_REVISION@:@LIBGPGME_LT_AGE@
|
@LIBGPGME_LT_CURRENT@:@LIBGPGME_LT_REVISION@:@LIBGPGME_LT_AGE@
|
||||||
libgpgme_glib_la_DEPENDENCIES = $(assuan_libobjs) \
|
libgpgme_glib_la_DEPENDENCIES = @LTLIBOBJS@ \
|
||||||
@LTLIBOBJS@ $(srcdir)/libgpgme.vers $(gpgme_deps)
|
$(srcdir)/libgpgme.vers $(gpgme_deps)
|
||||||
libgpgme_glib_la_LIBADD = $(assuan_libobjs) @LTLIBOBJS@ \
|
libgpgme_glib_la_LIBADD = @LIBASSUAN_LIBS@ @LTLIBOBJS@ \
|
||||||
@GPG_ERROR_LIBS@ @GLIB_LIBS@ @NETLIBS@
|
@GPG_ERROR_LIBS@ @GLIB_LIBS@ @NETLIBS@
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -219,9 +215,8 @@ if BUILD_W32_QT
|
|||||||
libgpgme_qt_la_LDFLAGS = $(gpgme_res_ldflag) $(no_undefined) \
|
libgpgme_qt_la_LDFLAGS = $(gpgme_res_ldflag) $(no_undefined) \
|
||||||
$(export_symbols) $(libgpgme_version_script_cmd) -version-info \
|
$(export_symbols) $(libgpgme_version_script_cmd) -version-info \
|
||||||
@LIBGPGME_LT_CURRENT@:@LIBGPGME_LT_REVISION@:@LIBGPGME_LT_AGE@
|
@LIBGPGME_LT_CURRENT@:@LIBGPGME_LT_REVISION@:@LIBGPGME_LT_AGE@
|
||||||
libgpgme_qt_la_DEPENDENCIES = $(assuan_libobjs) \
|
libgpgme_qt_la_DEPENDENCIES = @LTLIBOBJS@ $(srcdir)/libgpgme.vers $(gpgme_deps)
|
||||||
@LTLIBOBJS@ $(srcdir)/libgpgme.vers $(gpgme_deps)
|
libgpgme_qt_la_LIBADD = @LIBASSUAN_LIBS@ @LTLIBOBJS@ \
|
||||||
libgpgme_qt_la_LIBADD = $(assuan_libobjs) @LTLIBOBJS@ \
|
|
||||||
@GPG_ERROR_LIBS@ @QT4_CORE_LIBS@ @NETLIBS@
|
@GPG_ERROR_LIBS@ @QT4_CORE_LIBS@ @NETLIBS@
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -161,7 +161,7 @@ llass_cancel (void *engine)
|
|||||||
|
|
||||||
if (llass->assuan_ctx)
|
if (llass->assuan_ctx)
|
||||||
{
|
{
|
||||||
assuan_disconnect (llass->assuan_ctx);
|
assuan_release (llass->assuan_ctx);
|
||||||
llass->assuan_ctx = NULL;
|
llass->assuan_ctx = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,7 +213,10 @@ llass_new (void **engine, const char *file_name, const char *home_dir)
|
|||||||
llass->opt.gpg_agent = 1;
|
llass->opt.gpg_agent = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = assuan_socket_connect (&llass->assuan_ctx, file_name, 0);
|
err = assuan_new (&llass->assuan_ctx);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
err = assuan_socket_connect (llass->assuan_ctx, file_name, 0);
|
||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@ extern struct engine_ops _gpgme_engine_ops_gpgsm; /* CMS. */
|
|||||||
#ifdef ENABLE_GPGCONF
|
#ifdef ENABLE_GPGCONF
|
||||||
extern struct engine_ops _gpgme_engine_ops_gpgconf; /* gpg-conf. */
|
extern struct engine_ops _gpgme_engine_ops_gpgconf; /* gpg-conf. */
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_GPGSM /* If this is enabled we also have assuan support. */
|
#ifdef ENABLE_ASSUAN
|
||||||
extern struct engine_ops _gpgme_engine_ops_assuan; /* Low-level Assuan. */
|
extern struct engine_ops _gpgme_engine_ops_assuan; /* Low-level Assuan. */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -171,132 +171,6 @@ close_notify_handler (int fd, void *opaque)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static gpgme_error_t
|
|
||||||
map_assuan_error (gpg_error_t err)
|
|
||||||
{
|
|
||||||
if (!err)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (err == -1)
|
|
||||||
return gpg_error (GPG_ERR_INV_ENGINE);
|
|
||||||
|
|
||||||
/* New code will use gpg_error_t values. */
|
|
||||||
if (gpg_err_source (err))
|
|
||||||
return (gpgme_error_t) err;
|
|
||||||
|
|
||||||
/* Legacy code will use old values. */
|
|
||||||
switch (err)
|
|
||||||
{
|
|
||||||
case ASSUAN_No_Error:
|
|
||||||
return gpg_error (GPG_ERR_NO_ERROR);
|
|
||||||
case ASSUAN_General_Error:
|
|
||||||
return gpg_error (GPG_ERR_GENERAL);
|
|
||||||
case ASSUAN_Out_Of_Core:
|
|
||||||
return gpg_error (GPG_ERR_ENOMEM);
|
|
||||||
case ASSUAN_Invalid_Value:
|
|
||||||
return gpg_error (GPG_ERR_INV_VALUE);
|
|
||||||
case ASSUAN_Timeout:
|
|
||||||
return gpg_error (GPG_ERR_ETIMEDOUT);
|
|
||||||
case ASSUAN_Read_Error:
|
|
||||||
return gpg_error (GPG_ERR_GENERAL);
|
|
||||||
case ASSUAN_Write_Error:
|
|
||||||
return gpg_error (GPG_ERR_GENERAL);
|
|
||||||
|
|
||||||
case ASSUAN_Problem_Starting_Server:
|
|
||||||
case ASSUAN_Not_A_Server:
|
|
||||||
case ASSUAN_Not_A_Client:
|
|
||||||
case ASSUAN_Nested_Commands:
|
|
||||||
case ASSUAN_No_Data_Callback:
|
|
||||||
case ASSUAN_No_Inquire_Callback:
|
|
||||||
case ASSUAN_Connect_Failed:
|
|
||||||
case ASSUAN_Accept_Failed:
|
|
||||||
case ASSUAN_Invalid_Command:
|
|
||||||
case ASSUAN_Unknown_Command:
|
|
||||||
case ASSUAN_Syntax_Error:
|
|
||||||
case ASSUAN_Parameter_Error:
|
|
||||||
case ASSUAN_Parameter_Conflict:
|
|
||||||
case ASSUAN_No_Input:
|
|
||||||
case ASSUAN_No_Output:
|
|
||||||
case ASSUAN_No_Data_Available:
|
|
||||||
case ASSUAN_Too_Much_Data:
|
|
||||||
case ASSUAN_Inquire_Unknown:
|
|
||||||
case ASSUAN_Inquire_Error:
|
|
||||||
case ASSUAN_Invalid_Option:
|
|
||||||
case ASSUAN_Unexpected_Status:
|
|
||||||
case ASSUAN_Unexpected_Data:
|
|
||||||
case ASSUAN_Invalid_Status:
|
|
||||||
return gpg_error (GPG_ERR_ASSUAN);
|
|
||||||
|
|
||||||
case ASSUAN_Invalid_Response:
|
|
||||||
return gpg_error (GPG_ERR_INV_RESPONSE);
|
|
||||||
|
|
||||||
case ASSUAN_Not_Implemented:
|
|
||||||
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
|
||||||
case ASSUAN_Line_Too_Long:
|
|
||||||
return gpg_error (GPG_ERR_LINE_TOO_LONG);
|
|
||||||
case ASSUAN_Line_Not_Terminated:
|
|
||||||
return gpg_error (GPG_ERR_INCOMPLETE_LINE);
|
|
||||||
case ASSUAN_Canceled:
|
|
||||||
return gpg_error (GPG_ERR_CANCELED);
|
|
||||||
|
|
||||||
case ASSUAN_Unsupported_Algorithm:
|
|
||||||
return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
|
|
||||||
case ASSUAN_Server_Resource_Problem:
|
|
||||||
return gpg_error (GPG_ERR_RESOURCE_LIMIT);
|
|
||||||
case ASSUAN_Server_IO_Error:
|
|
||||||
return gpg_error (GPG_ERR_GENERAL);
|
|
||||||
case ASSUAN_Server_Bug:
|
|
||||||
return gpg_error (GPG_ERR_BUG);
|
|
||||||
case ASSUAN_Invalid_Data:
|
|
||||||
return gpg_error (GPG_ERR_INV_DATA);
|
|
||||||
case ASSUAN_Invalid_Index:
|
|
||||||
return gpg_error (GPG_ERR_INV_INDEX);
|
|
||||||
case ASSUAN_Not_Confirmed:
|
|
||||||
return gpg_error (GPG_ERR_NOT_CONFIRMED);
|
|
||||||
case ASSUAN_Bad_Certificate:
|
|
||||||
return gpg_error (GPG_ERR_BAD_CERT);
|
|
||||||
case ASSUAN_Bad_Certificate_Chain:
|
|
||||||
return gpg_error (GPG_ERR_BAD_CERT_CHAIN);
|
|
||||||
case ASSUAN_Missing_Certificate:
|
|
||||||
return gpg_error (GPG_ERR_MISSING_CERT);
|
|
||||||
case ASSUAN_Bad_Signature:
|
|
||||||
return gpg_error (GPG_ERR_BAD_SIGNATURE);
|
|
||||||
case ASSUAN_No_Agent:
|
|
||||||
return gpg_error (GPG_ERR_NO_AGENT);
|
|
||||||
case ASSUAN_Agent_Error:
|
|
||||||
return gpg_error (GPG_ERR_AGENT);
|
|
||||||
case ASSUAN_No_Public_Key:
|
|
||||||
return gpg_error (GPG_ERR_NO_PUBKEY);
|
|
||||||
case ASSUAN_No_Secret_Key:
|
|
||||||
return gpg_error (GPG_ERR_NO_SECKEY);
|
|
||||||
case ASSUAN_Invalid_Name:
|
|
||||||
return gpg_error (GPG_ERR_INV_NAME);
|
|
||||||
|
|
||||||
case ASSUAN_Cert_Revoked:
|
|
||||||
return gpg_error (GPG_ERR_CERT_REVOKED);
|
|
||||||
case ASSUAN_No_CRL_For_Cert:
|
|
||||||
return gpg_error (GPG_ERR_NO_CRL_KNOWN);
|
|
||||||
case ASSUAN_CRL_Too_Old:
|
|
||||||
return gpg_error (GPG_ERR_CRL_TOO_OLD);
|
|
||||||
case ASSUAN_Not_Trusted:
|
|
||||||
return gpg_error (GPG_ERR_NOT_TRUSTED);
|
|
||||||
|
|
||||||
case ASSUAN_Card_Error:
|
|
||||||
return gpg_error (GPG_ERR_CARD);
|
|
||||||
case ASSUAN_Invalid_Card:
|
|
||||||
return gpg_error (GPG_ERR_INV_CARD);
|
|
||||||
case ASSUAN_No_PKCS15_App:
|
|
||||||
return gpg_error (GPG_ERR_NO_PKCS15_APP);
|
|
||||||
case ASSUAN_Card_Not_Present:
|
|
||||||
return gpg_error (GPG_ERR_CARD_NOT_PRESENT);
|
|
||||||
case ASSUAN_Invalid_Id:
|
|
||||||
return gpg_error (GPG_ERR_INV_ID);
|
|
||||||
default:
|
|
||||||
return gpg_error (GPG_ERR_GENERAL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* This is the default inquiry callback. We use it to handle the
|
/* This is the default inquiry callback. We use it to handle the
|
||||||
Pinentry notifications. */
|
Pinentry notifications. */
|
||||||
static gpgme_error_t
|
static gpgme_error_t
|
||||||
@ -330,7 +204,7 @@ gpgsm_cancel (void *engine)
|
|||||||
|
|
||||||
if (gpgsm->assuan_ctx)
|
if (gpgsm->assuan_ctx)
|
||||||
{
|
{
|
||||||
assuan_disconnect (gpgsm->assuan_ctx);
|
assuan_release (gpgsm->assuan_ctx);
|
||||||
gpgsm->assuan_ctx = NULL;
|
gpgsm->assuan_ctx = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -450,13 +324,20 @@ gpgsm_new (void **engine, const char *file_name, const char *home_dir)
|
|||||||
argv[argc++] = "--server";
|
argv[argc++] = "--server";
|
||||||
argv[argc++] = NULL;
|
argv[argc++] = NULL;
|
||||||
|
|
||||||
|
err = assuan_new_ext (&gpgsm->assuan_ctx, GPG_ERR_SOURCE_GPGME,
|
||||||
|
&_gpgme_assuan_malloc_hooks, _gpgme_assuan_log_cb,
|
||||||
|
NULL);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
assuan_ctx_set_system_hooks (gpgsm->assuan_ctx, &_gpgme_assuan_system_hooks);
|
||||||
|
|
||||||
#if USE_DESCRIPTOR_PASSING
|
#if USE_DESCRIPTOR_PASSING
|
||||||
err = assuan_pipe_connect_ext
|
err = assuan_pipe_connect_ext
|
||||||
(&gpgsm->assuan_ctx, file_name ? file_name : _gpgme_get_gpgsm_path (),
|
(gpgsm->assuan_ctx, file_name ? file_name : _gpgme_get_gpgsm_path (),
|
||||||
argv, NULL, NULL, NULL, 1);
|
argv, NULL, NULL, NULL, 1);
|
||||||
#else
|
#else
|
||||||
err = assuan_pipe_connect
|
err = assuan_pipe_connect
|
||||||
(&gpgsm->assuan_ctx, file_name ? file_name : _gpgme_get_gpgsm_path (),
|
(gpgsm->assuan_ctx, file_name ? file_name : _gpgme_get_gpgsm_path (),
|
||||||
argv, child_fds);
|
argv, child_fds);
|
||||||
|
|
||||||
/* On Windows, handles are inserted in the spawned process with
|
/* On Windows, handles are inserted in the spawned process with
|
||||||
@ -504,11 +385,8 @@ gpgsm_new (void **engine, const char *file_name, const char *home_dir)
|
|||||||
NULL, NULL, NULL);
|
NULL, NULL, NULL);
|
||||||
free (optstr);
|
free (optstr);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
|
||||||
err = map_assuan_error (err);
|
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (isatty (1))
|
if (isatty (1))
|
||||||
{
|
{
|
||||||
@ -531,10 +409,7 @@ gpgsm_new (void **engine, const char *file_name, const char *home_dir)
|
|||||||
NULL, NULL, NULL);
|
NULL, NULL, NULL);
|
||||||
free (optstr);
|
free (optstr);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
|
||||||
err = map_assuan_error (err);
|
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
|
||||||
|
|
||||||
err = _gpgme_getenv ("TERM", &dft_ttytype);
|
err = _gpgme_getenv ("TERM", &dft_ttytype);
|
||||||
if (err)
|
if (err)
|
||||||
@ -553,13 +428,10 @@ gpgsm_new (void **engine, const char *file_name, const char *home_dir)
|
|||||||
NULL, NULL, NULL, NULL);
|
NULL, NULL, NULL, NULL);
|
||||||
free (optstr);
|
free (optstr);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
|
||||||
err = map_assuan_error (err);
|
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Ask gpgsm to enable the audit log support. */
|
/* Ask gpgsm to enable the audit log support. */
|
||||||
if (!err)
|
if (!err)
|
||||||
@ -662,8 +534,6 @@ gpgsm_set_locale (void *engine, int category, const char *value)
|
|||||||
err = assuan_transact (gpgsm->assuan_ctx, optstr, NULL, NULL,
|
err = assuan_transact (gpgsm->assuan_ctx, optstr, NULL, NULL,
|
||||||
NULL, NULL, NULL, NULL);
|
NULL, NULL, NULL, NULL);
|
||||||
free (optstr);
|
free (optstr);
|
||||||
if (err)
|
|
||||||
err = map_assuan_error (err);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
@ -684,13 +554,13 @@ gpgsm_assuan_simple_command (assuan_context_t ctx, char *cmd,
|
|||||||
|
|
||||||
err = assuan_write_line (ctx, cmd);
|
err = assuan_write_line (ctx, cmd);
|
||||||
if (err)
|
if (err)
|
||||||
return map_assuan_error (err);
|
return err;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
err = assuan_read_line (ctx, &line, &linelen);
|
err = assuan_read_line (ctx, &line, &linelen);
|
||||||
if (err)
|
if (err)
|
||||||
return map_assuan_error (err);
|
return err;
|
||||||
|
|
||||||
if (*line == '#' || !linelen)
|
if (*line == '#' || !linelen)
|
||||||
continue;
|
continue;
|
||||||
@ -702,7 +572,7 @@ gpgsm_assuan_simple_command (assuan_context_t ctx, char *cmd,
|
|||||||
else if (linelen >= 4
|
else if (linelen >= 4
|
||||||
&& line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
|
&& line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
|
||||||
&& line[3] == ' ')
|
&& line[3] == ' ')
|
||||||
err = map_assuan_error (atoi (&line[4]));
|
err = atoi (&line[4]);
|
||||||
else if (linelen >= 2
|
else if (linelen >= 2
|
||||||
&& line[0] == 'S' && line[1] == ' ')
|
&& line[0] == 'S' && line[1] == ' ')
|
||||||
{
|
{
|
||||||
@ -891,7 +761,6 @@ parse_status (const char *name)
|
|||||||
static gpgme_error_t
|
static gpgme_error_t
|
||||||
status_handler (void *opaque, int fd)
|
status_handler (void *opaque, int fd)
|
||||||
{
|
{
|
||||||
gpg_error_t assuan_err;
|
|
||||||
gpgme_error_t err = 0;
|
gpgme_error_t err = 0;
|
||||||
engine_gpgsm_t gpgsm = opaque;
|
engine_gpgsm_t gpgsm = opaque;
|
||||||
char *line;
|
char *line;
|
||||||
@ -899,23 +768,22 @@ status_handler (void *opaque, int fd)
|
|||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
assuan_err = assuan_read_line (gpgsm->assuan_ctx, &line, &linelen);
|
err = assuan_read_line (gpgsm->assuan_ctx, &line, &linelen);
|
||||||
if (assuan_err)
|
if (err)
|
||||||
{
|
{
|
||||||
/* Try our best to terminate the connection friendly. */
|
/* Try our best to terminate the connection friendly. */
|
||||||
/* assuan_write_line (gpgsm->assuan_ctx, "BYE"); */
|
/* assuan_write_line (gpgsm->assuan_ctx, "BYE"); */
|
||||||
err = map_assuan_error (assuan_err);
|
|
||||||
TRACE3 (DEBUG_CTX, "gpgme:status_handler", gpgsm,
|
TRACE3 (DEBUG_CTX, "gpgme:status_handler", gpgsm,
|
||||||
"fd 0x%x: error from assuan (%d) getting status line : %s",
|
"fd 0x%x: error from assuan (%d) getting status line : %s",
|
||||||
fd, assuan_err, gpg_strerror (err));
|
fd, err, gpg_strerror (err));
|
||||||
}
|
}
|
||||||
else if (linelen >= 3
|
else if (linelen >= 3
|
||||||
&& line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
|
&& line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
|
||||||
&& (line[3] == '\0' || line[3] == ' '))
|
&& (line[3] == '\0' || line[3] == ' '))
|
||||||
{
|
{
|
||||||
if (line[3] == ' ')
|
if (line[3] == ' ')
|
||||||
err = map_assuan_error (atoi (&line[4]));
|
err = atoi (&line[4]);
|
||||||
else
|
if (! err)
|
||||||
err = gpg_error (GPG_ERR_GENERAL);
|
err = gpg_error (GPG_ERR_GENERAL);
|
||||||
TRACE2 (DEBUG_CTX, "gpgme:status_handler", gpgsm,
|
TRACE2 (DEBUG_CTX, "gpgme:status_handler", gpgsm,
|
||||||
"fd 0x%x: ERR line - mapped to: %s",
|
"fd 0x%x: ERR line - mapped to: %s",
|
||||||
@ -1174,7 +1042,7 @@ start (engine_gpgsm_t gpgsm, const char *command)
|
|||||||
err = add_io_cb (gpgsm, &gpgsm->message_cb, _gpgme_data_outbound_handler);
|
err = add_io_cb (gpgsm, &gpgsm->message_cb, _gpgme_data_outbound_handler);
|
||||||
|
|
||||||
if (!err)
|
if (!err)
|
||||||
err = map_assuan_error (assuan_write_line (gpgsm->assuan_ctx, command));
|
err = assuan_write_line (gpgsm->assuan_ctx, command);
|
||||||
|
|
||||||
if (!err)
|
if (!err)
|
||||||
gpgsm_io_event (gpgsm, GPGME_EVENT_START, NULL);
|
gpgsm_io_event (gpgsm, GPGME_EVENT_START, NULL);
|
||||||
|
@ -278,7 +278,7 @@ get_max_fds (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
int
|
||||||
_gpgme_io_waitpid (int pid, int hang, int *r_status, int *r_signal)
|
_gpgme_io_waitpid (int pid, int hang, int *r_status, int *r_signal)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
|
@ -92,4 +92,10 @@ int _gpgme_io_fd2str (char *buf, int buflen, int fd);
|
|||||||
(in engine-gpgsm.c). */
|
(in engine-gpgsm.c). */
|
||||||
int _gpgme_io_dup (int fd);
|
int _gpgme_io_dup (int fd);
|
||||||
|
|
||||||
|
#ifndef HAVE_W32_SYSTEM
|
||||||
|
int _gpgme_io_recvmsg (int fd, struct msghdr *msg, int flags);
|
||||||
|
int _gpgme_io_sendmsg (int fd, const struct msghdr *msg, int flags);
|
||||||
|
int _gpgme_io_waitpid (int pid, int hang, int *r_status, int *r_signal);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* IO_H */
|
#endif /* IO_H */
|
||||||
|
10
src/util.h
10
src/util.h
@ -124,4 +124,14 @@ const char *_gpgme_get_w32spawn_path (void);
|
|||||||
#define GPG_ERR_NOT_OPERATIONAL 176
|
#define GPG_ERR_NOT_OPERATIONAL 176
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef ENABLE_ASSUAN
|
||||||
|
#include <assuan.h>
|
||||||
|
/* System hooks for assuan integration. */
|
||||||
|
extern struct assuan_system_hooks _gpgme_assuan_system_hooks;
|
||||||
|
extern struct assuan_malloc_hooks _gpgme_assuan_malloc_hooks;
|
||||||
|
int _gpgme_assuan_log_cb (assuan_context_t ctx, void *hook,
|
||||||
|
unsigned int cat, const char *msg);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* UTIL_H */
|
#endif /* UTIL_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user