+2003-08-18 Marcus Brinkmann <marcus@g10code.de>
+
+ * configure.ac: If building Assuan, check for funopen and
+ fopencookie, and make isascii, putc_unlocked and memrchr
+ replacement functions.
+
2003-07-31 Marcus Brinkmann <marcus@g10code.de>
* configure.ac (AC_INIT): Bump version to 0.4.3.
+2003-08-13 Werner Koch <wk@gnupg.org>
+
+ * assuan-inquire.c (assuan_inquire): Increase length of cmdbuf to
+ the Assuan limit.
+
+2003-06-24 Werner Koch <wk@gnupg.org>
+
+ * mkerrors: Kludge to print libgpg-error values in an easier
+ readable way.
+
+2003-04-29 Werner Koch <wk@gnupg.org>
+
+ * libassuan.m4: New. Based on libgrypt.m4.
+ * Makefile.am (m4data_DATA): New.
+
+ * assuan.h (AssuanCommand): Removed.
+
+ * assuan-handler.c: Remove the cmd_id element,
+ (assuan_register_command): Likewise. Note that semantics changed.
+ (_assuan_register_std_commands): Adjusted.
+
+2003-02-22 Neal H. Walfield <neal@g10code.de>
+
+ * Makefile.am (bin_SCRIPTS): Renamed from bin_PROGRAMS.
+
+2003-02-18 Neal H. Walfield <neal@g10code.de>
+
+ * Makefile.am (libassuan_a_LIBADD): New variable.
+ * funopen.c: Move from ../common.
+ * isascii.c: Likewise.
+ * memrchr.c: Likewise.
+ * putc_unlocked.c: Likewise.
+
+2003-02-18 Neal H. Walfield <neal@g10code.de>
+
+ * assuan-handler.c (_IO_cookie_io_functions_t): Remove.
+ (cookie_io_functions_t): Remove.
+ (fopencookie): Remove prototype.
+ (assuan_get_data_fp): Use funopen, not fopencookie.
+
+2003-02-18 Neal H. Walfield <neal@g10code.de>
+
+ * libassuan-config.in: New file.
+ * Makefile.am (bin_PROGRAMS): New variable.
+
+2003-02-17 Neal H. Walfield <neal@g10code.de>
+
+ * .cvsignore: New file.
+
+2003-02-17 Neal H. Walfield <neal@g10code.de>
+
+ * Makefile.am (lib_LIBRARIES): Use this instead of . . .
+ (noinst_LIBRARIES): . . . this.
+ (include_HEADERS): New variable.
+ (libassuan_a_SOURCES): Remove assuan.h, add assuan-logging.c.
+
+ * assuan.h (assuan_set_assuan_log_stream): New prototype.
+ (assuan_get_assuan_log_stream): Likewise.
+ (assuan_get_assuan_log_prefix): Likewise.
+ * assuan-logging.c: New file.
+
+ * assuan-buffer.c [HAVE_JNLIB_LOGGIN]: Do not include
+ "../jnlib/logging.h".
+ (my_log_prefix): Remove function.
+ (_assuan_read_line): Use assuan_get_assuan_log_prefix in lieu of
+ my_log_prefix.
+ (assuan_write_line): Likewise.
+ (_assuan_cookie_write_data): Likewise.
+ (_assuan_cookie_write_flush): Likewise.
+ * assuan-domain-connect.c (LOGERROR, LOGERROR1, LOGERROR2,
+ LOGERRORX): Remove.
+ (LOG): New macro.
+ (domain_reader): Use it.
+ (domain_writer): Likewise.
+ (domain_sendfd): Likewise.
+ (domain_receivefd): Likewise.
+ (_assuan_domain_init): Likewise.
+ (assuan_domain_connect): Likewise.
+ * assuan-pipe-connect.c [HAVE_JNLIB_LOGGIN]: Do not include
+ "../jnlib/logging.h".
+ (LOGERROR, LOGERROR1, LOGERROR2, LOGERRORX): Remove.
+ (LOG): New macro.
+ (assuan_pipe_connect): Use it.
+ * assuan-socket-connect.c [HAVE_JNLIB_LOGGIN]: Do not include
+ "../jnlib/logging.h".
+ (LOGERROR, LOGERROR1, LOGERROR2, LOGERRORX): Remove.
+ (LOG): New macro.
+ (assuan_socket_connect): Use it.
+ (socket_reader): Remove dead code.
+ (socket_writer): Likewise.
+ * assuan-util.c [HAVE_JNLIB_LOGGIN]: Do not include
+ "../jnlib/logging.h".
+ (_assuan_log_sanitized_string): Use assuan_get_assuan_log_stream,
+ not jnlib.
+
+2002-11-24 Neal H. Walfield <neal@g10code.de>
+
+ * assuan.h (assuan_command_parse_fd): New prototype.
+ * assuan-handler.c (assuan_command_parse_fd): Rename from
+ parse_cmd_input_output. Export.
+ (std_handler_input): Update to use assuan_command_parse_fd.
+ (std_handler_output): Likewise.
+
+2002-11-24 Neal H. Walfield <neal@g10code.de>
+
+ * assuan.h (assuan_sendfd): New prototype.
+ (assuan_receivefd): New prototype.
+ * assuan-buffer.c (assuan_sendfd): New function.
+ (assuan_receivefd): New function.
+ * assuan-handler.c (parse_cmd_input_output): Recognize incoming
+ file descriptors and act appropriately.
+ * assuan-defs.h (struct assuan_io): Add fields sendfd and
+ receivefd.
+ (struct assuan_context_s): Add fields pendingfds and
+ pendingfdscount.
+ * assuan-pipe-server.c (_assuan_new_context): Update IO to reflect
+ new features.
+ * assuan-domain-connect.c (do_deinit): Cleanup any unreceived file
+ descriptors.
+ (domain_reader): Receive file descriptors.
+ (domain_sendfd): New function.
+ (domain_receivefd): New function.
+ (_assuan_domain_init): Update initialization code to reflect new
+ features.
+
+2002-11-24 Neal H. Walfield <neal@g10code.de>
+
+ * assuan-domain-connect.c (do_finish): Remove.
+ (_assuan_domain_init): Use default handlers where possible.
+ Add an assert and update comments.
+ * assuan-domain-server.c (accept_connection): Remove.
+ (assuan_init_domain_server): Use default handlers where possible.
+ Put the server in pipe mode: it can only be used by a single
+ client.
+
+2002-11-24 Neal H. Walfield <neal@g10code.de>
+
+ * assuan.h: Add prototype for assuan_domain_connect and
+ assuan_init_domain_server.
+ * assuan-defs.h: Include <unistd.h>.
+ Add prototype for _assuan_domain_init.
+ * assuan-domain-connect.c: New file.
+ * assuan-domain-server.c: New file.
+ * Makefile.am (libassuan_a_SOURCES): Add assuan-domain-connect.c
+ and assuan-domain-server.c
+
+2002-11-23 Neal H. Walfield <neal@g10code.de>
+
+ * Makefile.am (libassuan_a_SOURCES): Add assuan-io.c.
+ * assuan-io.c: Restore.
+ (_assuan_simple_read): Rename from _assuan_read.
+ (_assuan_simple_write): Rename from _assuan_write.
+ * assuan-defs.h (_assuan_simple_read): New prototype.
+ (_assuan_simple_write): Likewise.
+ * assuan-pipe-server.c (pipe_reader): Remove.
+ (pipe_writer): Remove.
+ (_assuan_new_context): Initialize IO is with _assuan_simple_read
+ and _assuan_simple_write.
+ * assuan-socket-connect.c (socket_reader): Remove.
+ (socket_writer): Remove.
+ (assuan_socket_connect): Initialize IO is with _assuan_simple_read
+ and _assuan_simple_write.
+ * assuan-socket-server.c (io): New local variable.
+ (assuan_init_socket_server): Initialize CTX->io.
+ (assuan_init_connected_socket_server): Likewise.
+
+2002-11-23 Neal H. Walfield <neal@g10code.de>
+
+ * assuan-buffer.c (readline): Use memrchr.
+ (_assuan_read_line): Rewritten to use the string functions.
+
+2002-11-20 Neal H. Walfield <neal@g10code.de>
+
+ * assuan-socket-connect.c (assuan_socket_connect): Pass PF_LOCAL
+ to socket(), not AF_UNIX: it expects a PF_* macro and the former
+ is more portable.
+ (assuan_socket_connect): Use AF_LOCAL, not AF_UNIX which is more
+ POSIXy.
+
+2002-11-20 Neal H. Walfield <neal@g10code.de>
+
+ * assuan-defs.h (struct assuan_io): New structure.
+ (struct assuan_context_s): New field, io.
+ (_assuan_read): Depreciated.
+ (_assuan_write): Likewise.
+ * assuan-pipe-server.c: Include <unistd.h>.
+ (pipe_reader): New function.
+ (pipe_writer): Likewise.
+ (_assuan_new_context.IO): New local static. Set to pipe_reader
+ and pipe_writer. Use it to initialize new context.
+ * assuan-socket-connect.c (socket_reader): New function.
+ (socket_writer): New function.
+ (assuan_socket_connect.IO): New local static. Set to socket_reader
+ and socket_writer. Use it to initialize new context.
+ * assuan-buffer.c (writen): Take an ASSUAN_CONTEXT rather than a
+ file descriptor. Do not use _assuan_write but the write method
+ in the supplied context.
+ (readline): Likewise for _assuan_read.
+ (assuan_write_line): When calling writen, pass CTX; not the file
+ descriptor directly.
+ (_assuan_cookie_write_data): Likewise.
+ (_assuan_cookie_write_flush): Likewise.
+ (_assuan_read_line): Likewise for readline.
+ * Makefile.am (libassuan_a_SOURCES): Remove assuan-io.c.
+ * assuan-io.c: Removed.
+
2002-11-10 Werner Koch <wk@gnupg.org>
* assuan-pipe-connect.c (assuan_pipe_connect): Changed the order
* assuan-defs.h: Add space in the context for this.
- ***********************************************************
- * Please note that Assuan is maintained as part of GnuPG. *
- * You may find it source-copied in other packages. *
- ***********************************************************
-
Copyright 2001, 2002 Free Software Foundation, Inc.
This file is free software; as a special exception the author gives
# Assuan Makefile
-# Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+# Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
#
# This file is part of Assuan.
#
assuan-socket-server.c \
assuan-pipe-connect.c \
assuan-socket-connect.c \
- assuan-io.c
-
+ assuan-io.c \
+ assuan-domain-connect.c \
+ assuan-domain-server.c \
+ assuan-logging.c
assuan-errors.c : assuan.h
$(srcdir)/mkerrors < $(srcdir)/assuan.h > assuan-errors.c
-Please don't modify it here but in the copy which comes with GnuPG.
\ No newline at end of file
+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.
/* assuan-buffer.c - read and send data
- * Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
*
* This file is part of Assuan.
*
#include <assert.h>
#include "assuan-defs.h"
-#ifdef HAVE_JNLIB_LOGGING
-#include "../jnlib/logging.h"
-#endif
-
-
-static const char *
-my_log_prefix (void)
-{
-#ifdef HAVE_JNLIB_LOGGING
- return log_get_prefix (NULL);
-#else
- return "";
-#endif
-}
-
-
static int
-writen ( int fd, const char *buffer, size_t length )
+writen (ASSUAN_CONTEXT ctx, const char *buffer, size_t length)
{
while (length)
{
- ssize_t nwritten = _assuan_write (fd, buffer, length);
+ ssize_t nwritten = ctx->io->write (ctx, buffer, length);
if (nwritten < 0)
{
return 0; /* okay */
}
-/* read an entire line */
+/* Read an entire line. */
static int
-readline (int fd, char *buf, size_t buflen, int *r_nread, int *eof)
+readline (ASSUAN_CONTEXT ctx, char *buf, size_t buflen,
+ int *r_nread, int *eof)
{
size_t nleft = buflen;
char *p;
*r_nread = 0;
while (nleft > 0)
{
- ssize_t n = _assuan_read (fd, buf, nleft);
+ ssize_t n = ctx->io->read (ctx, buf, nleft);
if (n < 0)
{
nleft -= n;
buf += n;
*r_nread += n;
-
- for (; n && *p != '\n'; n--, p++)
- ;
- if (n)
+
+ p = memrchr (p, '\n', n);
+ if (p)
break; /* at least one full line available - that's enough for now */
}
_assuan_read_line (ASSUAN_CONTEXT ctx)
{
char *line = ctx->inbound.line;
- int n, nread, atticlen;
+ int nread, atticlen;
int rc;
+ char *endp = 0;
if (ctx->inbound.eof)
return -1;
{
memcpy (line, ctx->inbound.attic.line, atticlen);
ctx->inbound.attic.linelen = 0;
- for (n=0; n < atticlen && line[n] != '\n'; n++)
- ;
- if (n < atticlen)
+
+ endp = memchr (line, '\n', atticlen);
+ if (endp)
+ /* Found another line in the attic. */
{
- rc = 0; /* found another line in the attic */
+ rc = 0;
nread = atticlen;
atticlen = 0;
}
else
- { /* read the rest */
+ /* There is pending data but not a full line. */
+ {
assert (atticlen < LINELENGTH);
- rc = readline (ctx->inbound.fd, line + atticlen,
+ rc = readline (ctx, line + atticlen,
LINELENGTH - atticlen, &nread, &ctx->inbound.eof);
}
}
else
- rc = readline (ctx->inbound.fd, line, LINELENGTH,
+ /* No pending data. */
+ rc = readline (ctx, line, LINELENGTH,
&nread, &ctx->inbound.eof);
if (rc)
{
if (ctx->log_fp)
- fprintf (ctx->log_fp, "%s[%p] <- [Error: %s]\n",
- my_log_prefix (), ctx, strerror (errno));
+ fprintf (ctx->log_fp, "%s[%p] <- [Error: %s]\n",
+ assuan_get_assuan_log_prefix (), ctx, strerror (errno));
return ASSUAN_Read_Error;
}
if (!nread)
{
assert (ctx->inbound.eof);
if (ctx->log_fp)
- fprintf (ctx->log_fp, "%s[%p] <- [EOF]\n", my_log_prefix (),ctx);
- return -1;
+ fprintf (ctx->log_fp, "%s[%p] <- [EOF]\n",
+ assuan_get_assuan_log_prefix (), ctx);
+ return -1;
}
ctx->inbound.attic.pending = 0;
nread += atticlen;
- for (n=0; n < nread; n++)
+
+ if (! endp)
+ endp = memchr (line, '\n', nread);
+
+ if (endp)
{
- if (line[n] == '\n')
- {
- if (n+1 < nread)
- {
- char *s, *d;
- int i;
-
- n++;
- /* we have to copy the rest because the handlers are
- allowed to modify the passed buffer */
- for (d=ctx->inbound.attic.line, s=line+n, i=nread-n; i; i--)
- {
- if (*s=='\n')
- ctx->inbound.attic.pending = 1;
- *d++ = *s++;
- }
- ctx->inbound.attic.linelen = nread-n;
- n--;
- }
- if (n && line[n-1] == '\r')
- n--;
- line[n] = 0;
- ctx->inbound.linelen = n;
- if (ctx->log_fp)
- {
- fprintf (ctx->log_fp, "%s[%p] <- ", my_log_prefix (), ctx);
- 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;
- }
- }
+ 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 (ctx->log_fp)
- fprintf (ctx->log_fp, "%s[%p] <- [Invalid line]\n", my_log_prefix (), ctx);
- *line = 0;
- ctx->inbound.linelen = 0;
- return ctx->inbound.eof? ASSUAN_Line_Not_Terminated : ASSUAN_Line_Too_Long;
+ if (endp != line && endp[-1] == '\r')
+ endp --;
+ *endp = 0;
+
+ ctx->inbound.linelen = endp - line;
+ if (ctx->log_fp)
+ {
+ fprintf (ctx->log_fp, "%s[%p] <- ",
+ assuan_get_assuan_log_prefix (), ctx);
+ 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[%p] <- [Invalid line]\n",
+ assuan_get_assuan_log_prefix (), ctx);
+ *line = 0;
+ ctx->inbound.linelen = 0;
+ return ctx->inbound.eof ? ASSUAN_Line_Not_Terminated
+ : ASSUAN_Line_Too_Long;
+ }
}
AssuanError
-assuan_write_line (ASSUAN_CONTEXT ctx, const char *line )
+assuan_write_line (ASSUAN_CONTEXT ctx, const char *line)
{
int rc;
size_t len;
/* fixme: we should do some kind of line buffering. */
if (ctx->log_fp)
{
- fprintf (ctx->log_fp, "%s[%p] -> ", my_log_prefix (), ctx);
+ fprintf (ctx->log_fp, "%s[%p] -> ",
+ assuan_get_assuan_log_prefix (), ctx);
if (s)
- fputs ("[supplied line contained a LF]", ctx->log_fp);
+ fputs ("[supplied line contained a LF]", ctx->log_fp);
if (ctx->confidential)
- fputs ("[Confidential data not shown]", ctx->log_fp);
+ fputs ("[Confidential data not shown]", ctx->log_fp);
else
- _assuan_log_print_buffer (ctx->log_fp, line, len);
+ _assuan_log_print_buffer (ctx->log_fp, line, len);
putc ('\n', ctx->log_fp);
}
- rc = writen (ctx->outbound.fd, line, len);
+ rc = writen (ctx, line, len);
if (rc)
rc = ASSUAN_Write_Error;
if (!rc)
{
- rc = writen (ctx->outbound.fd, "\n", 1);
+ rc = writen (ctx, "\n", 1);
if (rc)
rc = ASSUAN_Write_Error;
}
{
if (ctx->log_fp)
{
- fprintf (ctx->log_fp, "%s[%p] -> ", my_log_prefix (), ctx);
+ fprintf (ctx->log_fp, "%s[%p] -> ",
+ assuan_get_assuan_log_prefix (), ctx);
+
if (ctx->confidential)
fputs ("[Confidential data not shown]", ctx->log_fp);
else
}
*line++ = '\n';
linelen++;
- if (writen (ctx->outbound.fd, ctx->outbound.data.line, linelen))
+ if (writen (ctx, ctx->outbound.data.line, linelen))
{
ctx->outbound.data.error = ASSUAN_Write_Error;
return 0;
if (linelen)
{
if (ctx->log_fp)
- {
- fprintf (ctx->log_fp, "%s[%p] -> ", my_log_prefix (), ctx);
- 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);
- }
+ {
+ fprintf (ctx->log_fp, "%s[%p] -> ",
+ assuan_get_assuan_log_prefix (), ctx);
+ 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 (writen (ctx->outbound.fd, ctx->outbound.data.line, linelen))
+ if (writen (ctx, ctx->outbound.data.line, linelen))
{
ctx->outbound.data.error = ASSUAN_Write_Error;
return 0;
return 0;
}
+
+AssuanError
+assuan_sendfd (ASSUAN_CONTEXT ctx, int fd)
+{
+ 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);
+}
+
+AssuanError
+assuan_receivefd (ASSUAN_CONTEXT ctx, int *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);
+}
#define ASSUAN_DEFS_H
#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
#include "assuan.h"
#define LINELENGTH ASSUAN_LINELENGTH
-struct cmdtbl_s {
+struct cmdtbl_s
+{
const char *name;
- int cmd_id;
int (*handler)(ASSUAN_CONTEXT, char *line);
};
-struct assuan_context_s {
+struct assuan_io
+{
+ /* Routine to read from input_fd. */
+ ssize_t (*read) (ASSUAN_CONTEXT, void *, size_t);
+ /* Routine to write to output_fd. */
+ ssize_t (*write) (ASSUAN_CONTEXT, const void *, size_t);
+ /* Send a file descriptor. */
+ AssuanError (*sendfd) (ASSUAN_CONTEXT, int);
+ /* Receive a file descriptor. */
+ AssuanError (*receivefd) (ASSUAN_CONTEXT, int *);
+};
+
+struct assuan_context_s
+{
AssuanError err_no;
const char *err_str;
int os_errno; /* last system error number used with certain error codes*/
pid_t client_pid; /* for a socket server the PID of the client or -1
if not available */
+ /* Used for Unix domain sockets. */
+ struct sockaddr_un myaddr;
+ struct sockaddr_un serveraddr;
+ /* When reading from datagram sockets, we must read an entire
+ message at a time. This means that we have to do our own
+ buffering to be able to get the semantics of read. */
+ void *domainbuffer;
+ /* Offset of start of buffer. */
+ int domainbufferoffset;
+ /* Bytes buffered. */
+ int domainbuffersize;
+ /* Memory allocated. */
+ int domainbufferallocated;
+
+ int *pendingfds;
+ int pendingfdscount;
+
void (*deinit_handler)(ASSUAN_CONTEXT);
int (*accept_handler)(ASSUAN_CONTEXT);
int (*finish_handler)(ASSUAN_CONTEXT);
int input_fd; /* set by INPUT command */
int output_fd; /* set by OUTPUT command */
+ /* io routines. */
+ struct assuan_io *io;
};
-
-
/*-- assuan-pipe-server.c --*/
int _assuan_new_context (ASSUAN_CONTEXT *r_ctx);
void _assuan_release_context (ASSUAN_CONTEXT ctx);
+/*-- assuan-domain-connect.c --*/
+/* 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. */
+AssuanError _assuan_domain_init (ASSUAN_CONTEXT *r_ctx,
+ int rendezvousfd,
+ pid_t peer);
/*-- assuan-handler.c --*/
int _assuan_register_std_commands (ASSUAN_CONTEXT ctx);
void _assuan_log_sanitized_string (const char *string);
/*-- assuan-io.c --*/
-
-/* Wraps the standard read and write functions to do the Right
- Thing depending on our linkage. */
-ssize_t _assuan_read (int fd, void *buffer, size_t size);
-ssize_t _assuan_write (int fd, const void *buffer, size_t size);
+ssize_t _assuan_simple_read (ASSUAN_CONTEXT ctx, void *buffer, size_t size);
+ssize_t _assuan_simple_write (ASSUAN_CONTEXT ctx, const void *buffer,
+ size_t size);
+
+#ifdef HAVE_FOPENCOOKIE
+/* We have to implement funopen in terms of glibc's fopencookie. */
+FILE *funopen(const void *cookie, cookie_read_function_t *readfn,
+ cookie_write_function_t *writefn,
+ cookie_seek_function_t *seekfn,
+ cookie_close_function_t *closefn);
+#endif /*HAVE_FOPENCOOKIE*/
#endif /*ASSUAN_DEFS_H*/
--- /dev/null
+/* assuan-domain-connect.c - Assuan unix domain socket based client
+ * Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <alloca.h>
+#include <string.h>
+#include <assert.h>
+
+#include "assuan-defs.h"
+
+#define LOG(format, args...) \
+ fprintf (assuan_get_assuan_log_stream (), \
+ assuan_get_assuan_log_prefix (), \
+ "%s" format , ## args)
+
+
+static void
+do_deinit (ASSUAN_CONTEXT ctx)
+{
+ if (ctx->inbound.fd != -1)
+ close (ctx->inbound.fd);
+ ctx->inbound.fd = -1;
+ ctx->outbound.fd = -1;
+
+ if (ctx->domainbuffer)
+ {
+ assert (ctx->domainbufferallocated);
+ free (ctx->domainbuffer);
+ }
+
+ if (ctx->pendingfds)
+ {
+ int i;
+
+ assert (ctx->pendingfdscount > 0);
+ for (i = 0; i < ctx->pendingfdscount; i ++)
+ close (ctx->pendingfds[i]);
+
+ free (ctx->pendingfds);
+ }
+
+ unlink (ctx->myaddr.sun_path);
+}
+
+
+/* Read from the socket server. */
+static ssize_t
+domain_reader (ASSUAN_CONTEXT ctx, void *buf, size_t buflen)
+{
+ int len = ctx->domainbuffersize;
+
+ start:
+ if (len == 0)
+ /* No data is buffered. */
+ {
+ struct msghdr msg;
+ struct iovec iovec;
+ struct sockaddr_un sender;
+ struct
+ {
+ struct cmsghdr hdr;
+ int fd;
+ }
+ cmsg;
+
+ memset (&msg, 0, sizeof (msg));
+
+ for (;;)
+ {
+ msg.msg_name = &sender;
+ msg.msg_namelen = sizeof (struct sockaddr_un);
+ msg.msg_iov = &iovec;
+ msg.msg_iovlen = 1;
+ iovec.iov_base = ctx->domainbuffer;
+ iovec.iov_len = ctx->domainbufferallocated;
+ msg.msg_control = &cmsg;
+ msg.msg_controllen = sizeof cmsg;
+
+ /* Peek first: if the buffer we have is too small then it
+ will be truncated. */
+ len = recvmsg (ctx->inbound.fd, &msg, MSG_PEEK);
+ if (len < 0)
+ {
+ printf ("domain_reader: %m\n");
+ return -1;
+ }
+
+ if (strcmp (ctx->serveraddr.sun_path,
+ ((struct sockaddr_un *) msg.msg_name)->sun_path) != 0)
+ {
+ /* XXX: Arg. Not from whom we expected! What do we
+ want to do? Should we just ignore it? Either way,
+ we still need to consume the message. */
+ break;
+ }
+
+ if (msg.msg_flags & MSG_TRUNC)
+ /* Enlarge the buffer and try again. */
+ {
+ int size = ctx->domainbufferallocated;
+ void *tmp;
+
+ if (size == 0)
+ size = 4 * 1024;
+ else
+ size *= 2;
+
+ tmp = malloc (size);
+ if (! tmp)
+ return -1;
+
+ free (ctx->domainbuffer);
+ ctx->domainbuffer = tmp;
+ ctx->domainbufferallocated = size;
+ }
+ else
+ /* We have enough space! */
+ break;
+ }
+
+ /* Now we have to actually consume it (remember, we only
+ peeked). */
+ msg.msg_name = &sender;
+ msg.msg_namelen = sizeof (struct sockaddr_un);
+ msg.msg_iov = &iovec;
+ msg.msg_iovlen = 1;
+ iovec.iov_base = ctx->domainbuffer;
+ iovec.iov_len = ctx->domainbufferallocated;
+ msg.msg_control = &cmsg;
+ msg.msg_controllen = sizeof cmsg;
+
+ if (strcmp (ctx->serveraddr.sun_path,
+ ((struct sockaddr_un *) msg.msg_name)->sun_path) != 0)
+ {
+ /* XXX: Arg. Not from whom we expected! What do we want to
+ do? Should we just ignore it? We shall do the latter
+ for the moment. */
+ LOG ("Not setup to receive messages from: `%s'.",
+ ((struct sockaddr_un *) msg.msg_name)->sun_path);
+ goto start;
+ }
+
+ len = recvmsg (ctx->inbound.fd, &msg, 0);
+ if (len < 0)
+ {
+ LOG ("domain_reader: %s\n", strerror (errno));
+ return -1;
+ }
+
+ ctx->domainbuffersize = len;
+ ctx->domainbufferoffset = 0;
+
+ if (sizeof (cmsg) == msg.msg_controllen)
+ /* We received a file descriptor. */
+ {
+ void *tmp;
+
+ tmp = realloc (ctx->pendingfds,
+ sizeof (int) * (ctx->pendingfdscount + 1));
+ if (! tmp)
+ {
+ LOG ("domain_reader: %s\n", strerror (errno));
+ return -1;
+ }
+
+ ctx->pendingfds = tmp;
+ ctx->pendingfds[ctx->pendingfdscount++]
+ = *(int *) CMSG_DATA (&cmsg.hdr);
+
+ LOG ("Received file descriptor %d from peer.\n",
+ ctx->pendingfds[ctx->pendingfdscount - 1]);
+ }
+
+ if (len == 0)
+ goto start;
+ }
+
+ /* Return some data to the user. */
+
+ if (len > buflen)
+ /* We have more than the user requested. */
+ len = buflen;
+
+ memcpy (buf, ctx->domainbuffer + ctx->domainbufferoffset, len);
+ ctx->domainbuffersize -= len;
+ assert (ctx->domainbuffersize >= 0);
+ ctx->domainbufferoffset += len;
+ assert (ctx->domainbufferoffset <= ctx->domainbufferallocated);
+
+ return len;
+}
+
+/* Write to the domain server. */
+static ssize_t
+domain_writer (ASSUAN_CONTEXT ctx, const void *buf, size_t buflen)
+{
+ struct msghdr msg;
+ struct iovec iovec;
+ ssize_t len;
+
+ memset (&msg, 0, sizeof (msg));
+
+ msg.msg_name = &ctx->serveraddr;
+ msg.msg_namelen = offsetof (struct sockaddr_un, sun_path)
+ + strlen (ctx->serveraddr.sun_path) + 1;
+
+ msg.msg_iovlen = 1;
+ msg.msg_iov = &iovec;
+ iovec.iov_base = (void *) buf;
+ iovec.iov_len = buflen;
+ msg.msg_control = 0;
+ msg.msg_controllen = 0;
+
+ len = sendmsg (ctx->outbound.fd, &msg, 0);
+ if (len < 0)
+ LOG ("domain_writer: %s\n", strerror (errno));
+
+ return len;
+}
+
+static AssuanError
+domain_sendfd (ASSUAN_CONTEXT ctx, int fd)
+{
+ struct msghdr msg;
+ struct
+ {
+ struct cmsghdr hdr;
+ int fd;
+ }
+ cmsg;
+ int len;
+
+ memset (&msg, 0, sizeof (msg));
+
+ msg.msg_name = &ctx->serveraddr;
+ msg.msg_namelen = offsetof (struct sockaddr_un, sun_path)
+ + strlen (ctx->serveraddr.sun_path) + 1;
+
+ msg.msg_iovlen = 0;
+ msg.msg_iov = 0;
+
+ cmsg.hdr.cmsg_level = SOL_SOCKET;
+ cmsg.hdr.cmsg_type = SCM_RIGHTS;
+ cmsg.hdr.cmsg_len = sizeof (cmsg);
+
+ msg.msg_control = &cmsg;
+ msg.msg_controllen = sizeof (cmsg);
+
+ *(int *) CMSG_DATA (&cmsg.hdr) = fd;
+
+ len = sendmsg (ctx->outbound.fd, &msg, 0);
+ if (len < 0)
+ {
+ LOG ("domain_sendfd: %s\n", strerror (errno));
+ return ASSUAN_General_Error;
+ }
+ else
+ return 0;
+}
+
+static AssuanError
+domain_receivefd (ASSUAN_CONTEXT ctx, int *fd)
+{
+ if (ctx->pendingfds == 0)
+ {
+ LOG ("No pending file descriptors!\n");
+ return ASSUAN_General_Error;
+ }
+
+ *fd = ctx->pendingfds[0];
+ if (-- ctx->pendingfdscount == 0)
+ {
+ free (ctx->pendingfds);
+ ctx->pendingfds = 0;
+ }
+ else
+ /* Fix the array. */
+ {
+ memmove (ctx->pendingfds, ctx->pendingfds + 1,
+ ctx->pendingfdscount * sizeof (int));
+ ctx->pendingfds = realloc (ctx->pendingfds,
+ ctx->pendingfdscount * sizeof (int));
+ }
+
+ return 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. */
+AssuanError
+_assuan_domain_init (ASSUAN_CONTEXT *r_ctx, int rendezvousfd, pid_t peer)
+{
+ static struct assuan_io io = { domain_reader, domain_writer,
+ domain_sendfd, domain_receivefd };
+
+ AssuanError err;
+ ASSUAN_CONTEXT ctx;
+ int fd;
+ size_t len;
+ int tries;
+
+ if (!r_ctx)
+ return ASSUAN_Invalid_Value;
+ *r_ctx = NULL;
+
+ err = _assuan_new_context (&ctx);
+ if (err)
+ return err;
+
+ /* Save it in case we need it later. */
+ ctx->pid = peer;
+
+ /* Override the default (NOP) handlers. */
+ ctx->deinit_handler = do_deinit;
+
+ /* Setup the socket. */
+
+ fd = socket (PF_LOCAL, SOCK_DGRAM, 0);
+ if (fd == -1)
+ {
+ LOG ("can't create socket: %s\n", strerror (errno));
+ _assuan_release_context (ctx);
+ return ASSUAN_General_Error;
+ }
+
+ ctx->inbound.fd = fd;
+ ctx->outbound.fd = fd;
+
+ /* And the io buffers. */
+
+ ctx->io = &io;
+ ctx->domainbuffer = 0;
+ ctx->domainbufferoffset = 0;
+ ctx->domainbuffersize = 0;
+ ctx->domainbufferallocated = 0;
+ ctx->pendingfds = 0;
+ ctx->pendingfdscount = 0;
+
+ /* Get usable name and bind to it. */
+
+ for (tries = 0; tries < TMP_MAX; tries ++)
+ {
+ char *p;
+ char buf[L_tmpnam];
+
+ /* XXX: L_tmpnam must be shorter than sizeof (sun_path)! */
+ assert (L_tmpnam < sizeof (ctx->myaddr.sun_path));
+
+ p = tmpnam (buf);
+ if (! p)
+ {
+ LOG ("cannot determine an appropriate temporary file "
+ "name. DOS in progress?\n");
+ _assuan_release_context (ctx);
+ close (fd);
+ return ASSUAN_General_Error;
+ }
+
+ memset (&ctx->myaddr, 0, sizeof ctx->myaddr);
+ ctx->myaddr.sun_family = AF_LOCAL;
+ len = strlen (buf) + 1;
+ memcpy (ctx->myaddr.sun_path, buf, len);
+ len += offsetof (struct sockaddr_un, sun_path);
+
+ err = bind (fd, (struct sockaddr *) &ctx->myaddr, len);
+ if (! err)
+ break;
+ }
+
+ if (err)
+ {
+ LOG ("can't bind to `%s': %s\n", ctx->myaddr.sun_path,
+ strerror (errno));
+ _assuan_release_context (ctx);
+ close (fd);
+ return ASSUAN_Connect_Failed;
+ }
+
+ /* Rendezvous with our peer. */
+ {
+ FILE *fp;
+ char *p;
+
+ fp = fdopen (rendezvousfd, "w+");
+ if (! fp)
+ {
+ LOG ("can't open rendezvous port: %s\n", strerror (errno));
+ return ASSUAN_Connect_Failed;
+ }
+
+ /* Send our address. */
+ fprintf (fp, "%s\n", ctx->myaddr.sun_path);
+ fflush (fp);
+
+ /* And receive our peer's. */
+ memset (&ctx->serveraddr, 0, sizeof ctx->serveraddr);
+ for (p = ctx->serveraddr.sun_path;
+ p < (ctx->serveraddr.sun_path
+ + sizeof ctx->serveraddr.sun_path - 1);
+ p ++)
+ {
+ *p = fgetc (fp);
+ if (*p == '\n')
+ break;
+ }
+ *p = '\0';
+ fclose (fp);
+
+ ctx->serveraddr.sun_family = AF_LOCAL;
+ }
+
+ *r_ctx = ctx;
+ return 0;
+}
+
+AssuanError
+assuan_domain_connect (ASSUAN_CONTEXT * r_ctx, int rendezvousfd, pid_t peer)
+{
+ AssuanError aerr;
+ int okay, off;
+
+ aerr = _assuan_domain_init (r_ctx, rendezvousfd, peer);
+ if (aerr)
+ return aerr;
+
+ /* Initial handshake. */
+ aerr = _assuan_read_from_server (*r_ctx, &okay, &off);
+ if (aerr)
+ LOG ("can't connect to server: %s\n", assuan_strerror (aerr));
+ else if (okay != 1)
+ {
+ LOG ("can't connect to server: `");
+ _assuan_log_sanitized_string ((*r_ctx)->inbound.line);
+ fprintf (assuan_get_assuan_log_stream (), "'\n");
+ aerr = ASSUAN_Connect_Failed;
+ }
+
+ if (aerr)
+ assuan_disconnect (*r_ctx);
+
+ return aerr;
+}
--- /dev/null
+/* assuan-socket-server.c - Assuan socket based server
+ * Copyright (C) 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <unistd.h>
+
+#include "assuan-defs.h"
+
+/* Initialize a server. */
+AssuanError
+assuan_init_domain_server (ASSUAN_CONTEXT *r_ctx,
+ int rendezvousfd,
+ pid_t peer)
+{
+ AssuanError err;
+
+ err = _assuan_domain_init (r_ctx, rendezvousfd, peer);
+ if (err)
+ return err;
+
+ (*r_ctx)->is_server = 1;
+ /* A domain server can only be used once. */
+ (*r_ctx)->pipe_mode = 1;
+
+ return 0;
+}
/* assuan-handler.c - dispatch commands
- * Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
*
* This file is part of Assuan.
*
#include "assuan-defs.h"
-#define spacep(p) (*(p) == ' ' || *(p) == '\t')
-#define digitp(a) ((a) >= '0' && (a) <= '9')
-#if !HAVE_FOPENCOOKIE
-/* Provide structure for our dummy replacement function. Usually this
- is defined in ../common/util.h but assuan should be self
- contained. */
-/* Fixme: Remove fopencoookie :-(( */
-typedef struct
-{
- ssize_t (*read)(void*,char*,size_t);
- ssize_t (*write)(void*,const char*,size_t);
- int (*seek)(void*,off_t*,int);
- int (*close)(void*);
-} _IO_cookie_io_functions_t;
-typedef _IO_cookie_io_functions_t cookie_io_functions_t;
-FILE *fopencookie (void *cookie, const char *opentype,
- cookie_io_functions_t funclist);
-#endif /*!HAVE_FOPENCOOKIE*/
+#define spacep(p) (*(p) == ' ' || *(p) == '\t')
+#define digitp(a) ((a) >= '0' && (a) <= '9')
+static int my_strcasecmp (const char *a, const char *b);
return set_error (ctx, Not_Implemented, NULL);
}
-static int
-parse_cmd_input_output (ASSUAN_CONTEXT ctx, char *line, int *rfd)
+AssuanError
+assuan_command_parse_fd (ASSUAN_CONTEXT ctx, char *line, int *rfd)
{
char *endp;
- if (strncmp (line, "FD=", 3))
- return set_error (ctx, Syntax_Error, "FD=<n> expected");
- line += 3;
- if (!digitp (*line))
- return set_error (ctx, Syntax_Error, "number required");
- *rfd = strtoul (line, &endp, 10);
- /* 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;
+ if (strncmp (line, "FD", 2) != 0 || (line[2] != '=' && line[2] != '\0'))
+ 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");
+ *rfd = strtoul (line, &endp, 10);
+ /* 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> */
{
int rc, fd;
- rc = parse_cmd_input_output (ctx, line, &fd);
+ rc = assuan_command_parse_fd (ctx, line, &fd);
if (rc)
return rc;
ctx->input_fd = fd;
{
int rc, fd;
- rc = parse_cmd_input_output (ctx, line, &fd);
+ rc = assuan_command_parse_fd (ctx, line, &fd);
if (rc)
return rc;
ctx->output_fd = fd;
/* This is a table with the standard commands and handler for them.
- The table is used to initialize a new context and assuciate strings
- and handlers with cmd_ids */
+ The table is used to initialize a new context and associate strings
+ with default handlers */
static struct {
const char *name;
- int cmd_id;
int (*handler)(ASSUAN_CONTEXT, char *line);
int always; /* always initialize this command */
} std_cmd_table[] = {
- { "NOP", ASSUAN_CMD_NOP, std_handler_nop, 1 },
- { "CANCEL", ASSUAN_CMD_CANCEL, std_handler_cancel, 1 },
- { "OPTION", ASSUAN_CMD_OPTION, std_handler_option, 1 },
- { "BYE", ASSUAN_CMD_BYE, std_handler_bye, 1 },
- { "AUTH", ASSUAN_CMD_AUTH, std_handler_auth, 1 },
- { "RESET", ASSUAN_CMD_RESET, std_handler_reset, 1 },
- { "END", ASSUAN_CMD_END, std_handler_end, 1 },
-
- { "INPUT", ASSUAN_CMD_INPUT, std_handler_input },
- { "OUTPUT", ASSUAN_CMD_OUTPUT, std_handler_output },
- { "OPTION", ASSUAN_CMD_OPTION, std_handler_option, 1 },
+ { "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 },
+
+ { "INPUT", std_handler_input },
+ { "OUTPUT", std_handler_output },
+ { "OPTION", std_handler_option, 1 },
{ NULL }
};
/**
* assuan_register_command:
* @ctx: the server context
- * @cmd_id: An ID value for the command
* @cmd_name: A string with the command name
- * @handler: The handler function to be called
- *
- * Register a handler to be used for a given command.
+ * @handler: The handler function to be called or NULL to use a default
+ * handler.
*
- * The @cmd_name must be %NULL or an empty string for all @cmd_ids
- * below %ASSUAN_CMD_USER because predefined values are used.
+ * 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:
+ * Return value: 0 on success or an error code
**/
int
assuan_register_command (ASSUAN_CONTEXT ctx,
- int cmd_id, const char *cmd_name,
+ const char *cmd_name,
int (*handler)(ASSUAN_CONTEXT, char *))
{
int i;
+ const char *s;
if (cmd_name && !*cmd_name)
cmd_name = NULL;
- if (cmd_id < ASSUAN_CMD_USER)
- {
- if (cmd_name)
- return ASSUAN_Invalid_Value; /* must be NULL for these values*/
+ if (!cmd_name)
+ return ASSUAN_Invalid_Value;
- for (i=0; std_cmd_table[i].name; i++)
- {
- if (std_cmd_table[i].cmd_id == cmd_id)
- {
- cmd_name = std_cmd_table[i].name;
- if (!handler)
- handler = std_cmd_table[i].handler;
- break;
- }
+ 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 (!std_cmd_table[i].name)
- return ASSUAN_Invalid_Value; /* not a pre-registered one */
+ if (s)
+ handler = std_cmd_table[i].handler;
+ if (!handler)
+ handler = dummy_handler; /* Last resort is the dummy handler. */
}
- if (!handler)
- handler = dummy_handler;
-
- if (!cmd_name)
- return ASSUAN_Invalid_Value;
-
-/* fprintf (stderr, "DBG-assuan: registering %d as `%s'\n", cmd_id, cmd_name); */
-
if (!ctx->cmdtbl)
{
ctx->cmdtbl_size = 50;
}
ctx->cmdtbl[ctx->cmdtbl_used].name = cmd_name;
- ctx->cmdtbl[ctx->cmdtbl_used].cmd_id = cmd_id;
ctx->cmdtbl[ctx->cmdtbl_used].handler = handler;
ctx->cmdtbl_used++;
return 0;
{
if (std_cmd_table[i].always)
{
- rc = assuan_register_command (ctx, std_cmd_table[i].cmd_id,
- NULL, NULL);
+ rc = assuan_register_command (ctx, std_cmd_table[i].name, NULL);
if (rc)
return rc;
}
FILE *
assuan_get_data_fp (ASSUAN_CONTEXT ctx)
{
- cookie_io_functions_t cookie_fnc;
-
if (ctx->outbound.data.fp)
return ctx->outbound.data.fp;
- cookie_fnc.read = NULL;
- cookie_fnc.write = _assuan_cookie_write_data;
- cookie_fnc.seek = NULL;
- cookie_fnc.close = _assuan_cookie_write_flush;
- ctx->outbound.data.fp = fopencookie (ctx, "wb", cookie_fnc);
+ ctx->outbound.data.fp = funopen (ctx, 0,
+ _assuan_cookie_write_data,
+ 0, _assuan_cookie_write_flush);
ctx->outbound.data.error = 0;
return ctx->outbound.data.fp;
}
/* assuan-inquire.c - handle inquire stuff
- * Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
*
* This file is part of Assuan.
*
#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
-struct membuf {
+struct membuf
+{
size_t len;
size_t size;
char *buf;
{
AssuanError rc;
struct membuf mb;
- char cmdbuf[100];
+ char cmdbuf[LINELENGTH-10]; /* (10 = strlen ("INQUIRE ")+CR,LF) */
unsigned char *line, *p;
int linelen;
int nodataexpected;
-/* assuan-buffer.c - Wraps the read and write functions.
+/* assuan-io.c - Wraps the read and write functions.
* Copyright (C) 2002 Free Software Foundation, Inc.
*
* This file is part of Assuan.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
+#include "assuan-defs.h"
#include <sys/types.h>
#include <unistd.h>
#pragma weak pth_write
ssize_t
-_assuan_read (int fd, void *buffer, size_t size)
+_assuan_simple_read (ASSUAN_CONTEXT ctx, void *buffer, size_t size)
{
- static ssize_t (*reader) (int, void *, size_t);
-
- if (! reader)
- {
- if (pth_read)
- reader = pth_read;
- else
- reader = read;
- }
-
- return reader (fd, buffer, size);
+ return (pth_read ? pth_read : read) (ctx->inbound.fd, buffer, size);
}
ssize_t
-_assuan_write (int fd, const void *buffer, size_t size)
+_assuan_simple_write (ASSUAN_CONTEXT ctx, const void *buffer, size_t size)
{
- static ssize_t (*writer) (int, const void *, size_t);
-
- if (! writer)
- {
- if (pth_write)
- writer = pth_write;
- else
- writer = write;
- }
-
- return writer (fd, buffer, size);
+ return (pth_write ? pth_write : write) (ctx->outbound.fd, buffer, size);
}
* assuan_accept:
* @ctx: context
*
- * Cancel any existing connectiion and wait for a connection from a
+ * 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.
*
--- /dev/null
+/* assuan-logging.c - Default logging function.
+ * Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "assuan-defs.h"
+#include <stdio.h>
+
+static FILE *_assuan_log;
+
+void
+assuan_set_assuan_log_stream (FILE *fp)
+{
+ _assuan_log = fp;
+}
+
+FILE *
+assuan_get_assuan_log_stream (void)
+{
+ return _assuan_log ? _assuan_log : stderr;
+}
+
+const char *
+assuan_get_assuan_log_prefix (void)
+{
+ return "";
+}
/* assuan-pipe-connect.c - Establish a pipe connection (client)
- * Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
*
* This file is part of Assuan.
*
#define MAX_OPEN_FDS 20
#endif
-#ifdef HAVE_JNLIB_LOGGING
-#include "../jnlib/logging.h"
-#define LOGERROR1(a,b) log_error ((a), (b))
-#else
-#define LOGERROR1(a,b) fprintf (stderr, (a), (b))
-#endif
-
-
+#define LOG(format, args...) \
+ fprintf (assuan_get_assuan_log_stream (), \
+ assuan_get_assuan_log_prefix (), \
+ "%s" format , ## args)
static int
-writen ( int fd, const char *buffer, size_t length )
+writen (int fd, const char *buffer, size_t length)
{
while (length)
{
/* Dup handles to stdin/stdout. */
if (rp[1] != STDOUT_FILENO)
- {
- if (dup2 (rp[1], STDOUT_FILENO) == -1)
- {
- LOGERROR1 ("dup2 failed in child: %s\n", strerror (errno));
- _exit (4);
- }
- }
+ {
+ if (dup2 (rp[1], STDOUT_FILENO) == -1)
+ {
+ LOG ("dup2 failed in child: %s\n", strerror (errno));
+ _exit (4);
+ }
+ }
if (wp[0] != STDIN_FILENO)
- {
- if (dup2 (wp[0], STDIN_FILENO) == -1)
- {
- LOGERROR1 ("dup2 failed in child: %s\n", strerror (errno));
- _exit (4);
- }
- }
+ {
+ if (dup2 (wp[0], STDIN_FILENO) == -1)
+ {
+ LOG ("dup2 failed in child: %s\n", strerror (errno));
+ _exit (4);
+ }
+ }
/* Dup stderr to /dev/null unless it is in the list of FDs to be
passed to the child. */
int fd = open ("/dev/null", O_WRONLY);
if (fd == -1)
{
- LOGERROR1 ("can't open `/dev/null': %s\n", strerror (errno));
+ LOG ("can't open `/dev/null': %s\n", strerror (errno));
_exit (4);
- }
- if (dup2 (fd, STDERR_FILENO) == -1)
- {
- LOGERROR1 ("dup2(dev/null, 2) failed: %s\n", strerror (errno));
- _exit (4);
- }
- }
+ }
+ if (dup2 (fd, STDERR_FILENO) == -1)
+ {
+ LOG ("dup2(dev/null, 2) failed: %s\n", strerror (errno));
+ _exit (4);
+ }
+ }
/* Close all files which will not be duped and are not in the
err = _assuan_read_from_server (*ctx, &okay, &off);
if (err)
- {
- LOGERROR1 ("can't connect server: %s\n", assuan_strerror (err));
- }
+ LOG ("can't connect server: %s\n", assuan_strerror (err));
else if (okay != 1)
{
- LOGERROR1 ("can't connect server: `%s'\n", (*ctx)->inbound.line);
- err = ASSUAN_Connect_Failed;
+ LOG ("can't connect server: `%s'\n", (*ctx)->inbound.line);
+ err = ASSUAN_Connect_Failed;
}
}
#include <config.h>
#include <stdlib.h>
#include <stdio.h>
+#include <unistd.h>
#include "assuan-defs.h"
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 *r_ctx)
{
+ static struct assuan_io io = { _assuan_simple_read,
+ _assuan_simple_write,
+ 0, 0 };
+
ASSUAN_CONTEXT ctx;
int rc;
ctx->inbound.fd = -1;
ctx->outbound.fd = -1;
+ ctx->io = &io;
ctx->listen_fd = -1;
ctx->client_pid = (pid_t)-1;
- /* use the pipe server handler as a default */
+ /* Use the pipe server handler as a default. */
ctx->deinit_handler = deinit_pipe_server;
ctx->accept_handler = accept_connection;
ctx->finish_handler = finish_connection;
if (ctx)
{
/* We use this function pointer to avoid linking other server
- when not needed but still allow for a generic deinit function */
+ when not needed but still allow for a generic deinit function. */
ctx->deinit_handler (ctx);
ctx->deinit_handler = NULL;
_assuan_release_context (ctx);
/* assuan-socket-connect.c - Assuan socket based client
- * Copyright (C) 2002 Free Software Foundation, Inc.
+ * Copyright (C) 2002, 2003 Free Software Foundation, Inc.
*
* This file is part of Assuan.
*
#include "assuan-defs.h"
-#ifdef HAVE_JNLIB_LOGGING
-#include "../jnlib/logging.h"
-#define LOGERROR(a) log_error ((a))
-#define LOGERROR1(a,b) log_error ((a), (b))
-#define LOGERROR2(a,b,c) log_error ((a), (b), (c))
-#define LOGERRORX(a) log_printf ((a))
-#else
-#define LOGERROR(a) fprintf (stderr, (a))
-#define LOGERROR1(a,b) fprintf (stderr, (a), (b))
-#define LOGERROR2(a,b,c) fprintf (stderr, (a), (b), (c))
-#define LOGERRORX(a) fputs ((a), stderr)
-#endif
-
-
+#define LOG(format, args...) \
+ fprintf (assuan_get_assuan_log_stream (), \
+ assuan_get_assuan_log_prefix (), \
+ "%s" format , ## args)
static int
do_finish (ASSUAN_CONTEXT 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. */
+ become handy in the future. */
AssuanError
assuan_socket_connect (ASSUAN_CONTEXT *r_ctx,
const char *name, pid_t server_pid)
{
+ static struct assuan_io io = { _assuan_simple_read,
+ _assuan_simple_write };
+
AssuanError err;
ASSUAN_CONTEXT ctx;
int fd;
ctx->deinit_handler = do_deinit;
ctx->finish_handler = do_finish;
- fd = socket (AF_UNIX, SOCK_STREAM, 0);
+ fd = socket (PF_LOCAL, SOCK_STREAM, 0);
if (fd == -1)
{
- LOGERROR1 ("can't create socket: %s\n", strerror (errno));
+ LOG ("can't create socket: %s\n", strerror (errno));
_assuan_release_context (ctx);
return ASSUAN_General_Error;
}
-
- memset (&srvr_addr, 0, sizeof srvr_addr );
- srvr_addr.sun_family = AF_UNIX;
- strcpy (srvr_addr.sun_path, name);
- len = (offsetof (struct sockaddr_un, sun_path)
- + strlen (srvr_addr.sun_path) + 1);
-
- if (connect (fd, (struct sockaddr*)&srvr_addr, len) == -1)
+
+ memset (&srvr_addr, 0, sizeof srvr_addr);
+ srvr_addr.sun_family = AF_LOCAL;
+ len = strlen (srvr_addr.sun_path) + 1;
+ memcpy (srvr_addr.sun_path, name, len);
+ len += (offsetof (struct sockaddr_un, sun_path));
+
+ if (connect (fd, (struct sockaddr *) &srvr_addr, len) == -1)
{
- LOGERROR2 ("can't connect to `%s': %s\n", name, strerror (errno));
+ LOG ("can't connect to `%s': %s\n", name, strerror (errno));
_assuan_release_context (ctx);
- close (fd );
+ close (fd);
return ASSUAN_Connect_Failed;
}
ctx->inbound.fd = fd;
ctx->outbound.fd = fd;
+ ctx->io = &io;
/* initial handshake */
{
err = _assuan_read_from_server (ctx, &okay, &off);
if (err)
- {
- LOGERROR1 ("can't connect server: %s\n", assuan_strerror (err));
- }
+ LOG ("can't connect to server: %s\n", assuan_strerror (err));
else if (okay != 1)
{
- LOGERROR ("can't connect server: `");
- _assuan_log_sanitized_string (ctx->inbound.line);
- LOGERRORX ("'\n");
- err = ASSUAN_Connect_Failed;
+ LOG ("can't connect to server: `");
+ _assuan_log_sanitized_string (ctx->inbound.line);
+ fprintf (assuan_get_assuan_log_stream (), "'\n");
+ err = ASSUAN_Connect_Failed;
}
}
*r_ctx = ctx;
return 0;
}
-
-
finish_connection (ctx);
}
-
+static struct assuan_io io = { _assuan_simple_read,
+ _assuan_simple_write };
/* Initialize a server for the socket LISTEN_FD which has already be
put into listen mode */
ctx->accept_handler = accept_connection;
ctx->finish_handler = finish_connection;
+ ctx->io = &io;
+
rc = _assuan_register_std_commands (ctx);
if (rc)
xfree (ctx);
if (!ctx)
return ASSUAN_Out_Of_Core;
ctx->is_server = 1;
- ctx->pipe_mode = 1; /* we wan't a second accept to indicate EOF */
+ ctx->pipe_mode = 1; /* we want a second accept to indicate EOF */
ctx->input_fd = -1;
ctx->output_fd = -1;
ctx->inbound.fd = -1;
ctx->outbound.fd = -1;
+ ctx->io = &io;
+
ctx->listen_fd = -1;
ctx->connected_fd = fd;
ctx->deinit_handler = deinit_socket_server;
/* assuan-util.c - Utility functions for Assuan
- * Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
*
* This file is part of Assuan.
*
#include "assuan-defs.h"
-#ifdef HAVE_JNLIB_LOGGING
-#include "../jnlib/logging.h"
-#endif
-
static void *(*alloc_func)(size_t n) = malloc;
static void *(*realloc_func)(void *p, size_t n) = realloc;
static void (*free_func)(void*) = free;
}
}
-
/* Log a user supplied string. Escapes non-printable before
printing. */
void
_assuan_log_sanitized_string (const char *string)
{
const unsigned char *s = string;
-#ifdef HAVE_JNLIB_LOGGING
- FILE *fp = log_get_stream ();
-#else
- FILE *fp = stderr;
-#endif
+ FILE *fp = assuan_get_assuan_log_stream ();
if (! *s)
return;
funlockfile (fp);
#endif
}
-
-
/* assuan.c - Definitions for the Assuan protocol
- * Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
*
* This file is part of Assuan.
*
#include <stdio.h>
#include <sys/types.h>
-#include <unistd.h> /* for ssize_t */
+#include <unistd.h>
#ifdef __cplusplus
-extern "C" {
-#if 0
- }
-#endif
+extern "C"
+{
#endif
-typedef enum {
+typedef enum
+{
ASSUAN_No_Error = 0,
ASSUAN_General_Error = 1,
ASSUAN_Out_Of_Core = 2,
ASSUAN_Invalid_Value = 3,
- ASSUAN_Timeout = 4,
+ ASSUAN_Timeout = 4,
ASSUAN_Read_Error = 5,
ASSUAN_Write_Error = 6,
ASSUAN_Problem_Starting_Server = 7,
} AssuanError;
/* This is a list of pre-registered ASSUAN commands */
-typedef enum {
+typedef enum
+{
ASSUAN_CMD_NOP = 0,
ASSUAN_CMD_CANCEL, /* cancel the current request */
ASSUAN_CMD_BYE,
/*-- assuan-handler.c --*/
int assuan_register_command (ASSUAN_CONTEXT ctx,
- int cmd_id, const char *cmd_string,
+ const char *cmd_string,
int (*handler)(ASSUAN_CONTEXT, char *));
int assuan_register_bye_notify (ASSUAN_CONTEXT ctx,
void (*fnc)(ASSUAN_CONTEXT));
void assuan_write_status (ASSUAN_CONTEXT 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). */
+AssuanError assuan_command_parse_fd (ASSUAN_CONTEXT ctx, char *line,
+ int *rfd);
/*-- assuan-listen.c --*/
AssuanError assuan_set_hello_line (ASSUAN_CONTEXT ctx, const char *line);
AssuanError assuan_socket_connect (ASSUAN_CONTEXT *ctx, const char *name,
pid_t server_pid);
+/*-- assuan-domain-connect.c --*/
+
+/* Connect to a Unix domain socket server. RENDEZVOUSFD is
+ bidirectional file descriptor (normally returned via socketpair)
+ which the client can use to rendezvous with the server. SERVER s
+ the server's pid. */
+AssuanError assuan_domain_connect (ASSUAN_CONTEXT *r_ctx,
+ int rendezvousfd,
+ pid_t server);
+
+/*-- assuan-domain-server.c --*/
+
+/* RENDEZVOUSFD is a bidirectional file descriptor (normally returned
+ via socketpair) that the domain server can use to rendezvous with
+ the client. CLIENT is the client's pid. */
+AssuanError assuan_init_domain_server (ASSUAN_CONTEXT *r_ctx,
+ int rendezvousfd,
+ pid_t client);
+
+
/*-- assuan-connect.c --*/
void assuan_disconnect (ASSUAN_CONTEXT ctx);
pid_t assuan_get_pid (ASSUAN_CONTEXT ctx);
AssuanError assuan_send_data (ASSUAN_CONTEXT ctx,
const void *buffer, size_t length);
+/* The file descriptor must be pending before assuan_receivefd is
+ call. This means that assuan_sendfd should be called *before* the
+ trigger is sent (normally via assuan_send_data ("I sent you a
+ descriptor")). */
+AssuanError assuan_sendfd (ASSUAN_CONTEXT ctx, int fd);
+AssuanError assuan_receivefd (ASSUAN_CONTEXT ctx, int *fd);
/*-- assuan-util.c --*/
void assuan_set_malloc_hooks ( void *(*new_alloc_func)(size_t n),
/*-- assuan-errors.c (built) --*/
const char *assuan_strerror (AssuanError err);
+/*-- assuan-logging.c --*/
+
+/* Set the stream to which assuan should log. By default, this is
+ stderr. */
+extern void assuan_set_assuan_log_stream (FILE *fp);
+
+/* Return the stream which is currently being using for logging. */
+extern FILE *assuan_get_assuan_log_stream (void);
+
+/* User defined call back. 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. "" */
+extern const char *assuan_get_assuan_log_prefix (void);
#ifdef __cplusplus
}
#endif
-#endif /*ASSUAN_H*/
+#endif /* ASSUAN_H */
assuan_strerror (AssuanError err)
{
const char *s;
- static char buf[25];
+ static char buf[50];
switch (err)
{
'
cat <<EOF
- default: sprintf (buf, "ec=%d", err ); s=buf; break;
+ default:
+ {
+ unsigned int source, code;
+
+ source = ((err >> 24) & 0xff);
+ code = (err & 0x00ffffff);
+ if (source) /* Assume this is an libgpg-error. */
+ sprintf (buf, "ec=%u.%u", source, code );
+ else
+ sprintf (buf, "ec=%d", err );
+ s=buf; break;
+ }
}
return s;
AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of this package])
AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version of this package])
-dnl Don't default to build static libs.
-dnl AC_DISABLE_STATIC
+# Don't default to build static libs.
+AC_DISABLE_STATIC
AC_PROG_LIBTOOL
AC_CANONICAL_HOST
AC_DEFINE(HAVE_PTHREAD, ,[Define if we have pthread.])
fi
-dnl # XXX: Probably use exec-prefix here?
-dnl GPG_DEFAULT='/usr/bin/gpg'
-dnl GPGSM_DEFAULT='/usr/bin/gpgsm'
+ # XXX: Probably use exec-prefix here?
+# GPG_DEFAULT='/usr/bin/gpg'
+# GPGSM_DEFAULT='/usr/bin/gpgsm'
;;
esac
AM_CONDITIONAL(HAVE_DOSISH_SYSTEM, test "$have_dosish_system" = "yes")
AM_CONDITIONAL(HAVE_PTH, test "$have_pth" = "yes")
AM_CONDITIONAL(HAVE_PTHREAD, test "$have_pthread" = "yes")
-dnl
-dnl Checks for header files.
-dnl
+
+# Checks for header files.
AC_CHECK_HEADERS(sys/select.h)
-dnl
-dnl Type checks.
-dnl
+# Type checks.
AC_CHECK_SIZEOF(unsigned int)
-dnl
-dnl Checks for compiler features.
-dnl
+# Checks for compiler features.
if test "$GCC" = yes; then
CFLAGS="$CFLAGS -Wall -Wcast-align -Wshadow -Wstrict-prototypes"
fi
-dnl
-dnl Checks for library functions.
-dnl
+# Checks for library functions.
AC_REPLACE_FUNCS(stpcpy)
AC_REPLACE_FUNCS(vasprintf)
GNUPG_CHECK_VA_COPY
fi
-# Note: fopencokie is only a dummy stub and not used.
-# However some code in assuan/ links against it.
-AC_REPLACE_FUNCS(fopencookie)
-
AM_PATH_GPG_ERROR(0.1,, AC_MSG_ERROR([libgpg-error was not found]))
AC_DEFINE(GPG_ERR_SOURCE_DEFAULT, GPG_ERR_SOURCE_GPGME,
[The default error source for GPGME.])
-dnl
-dnl Checks for system services
-dnl
+# Checks for system services
NO_OVERRIDE=no
AC_ARG_WITH(gpg,
AC_HELP_STRING([--with-gpg=PATH], [use GnuPG binary at PATH]),
AM_CONDITIONAL(RUN_GPGSM_TESTS,
[test "$cross_compiling" != "yes" && test -n "$GPGSM" && test -r "$GPGSM"])
-dnl FIXME: Only build if supported.
+# FIXME: Only build if supported.
AM_CONDITIONAL(BUILD_ASSUAN, test "$GPGSM" != "no")
+if test "$GPGSM" != "no"; then
+ AC_CHECK_FUNCS(funopen)
+ if test $ac_cv_func_funopen != yes; then
+ # No funopen but we can implement that in terms of fopencookie.
+ AC_CHECK_FUNCS(fopencookie, AC_LIBOBJ(funopen),
+ AC_MSG_ERROR([[
+No implementation of fopencookie or funopen available.
+]]))
+ fi
+
+ AC_REPLACE_FUNCS(isascii)
+ AC_REPLACE_FUNCS(putc_unlocked)
+ AC_REPLACE_FUNCS(memrchr)
+fi
+
+
AM_CONDITIONAL(BUILD_COMPLUS, test "$component_system" = "COM+")
dnl Make the version number in gpgme/gpgme.h the same as the one here.
+2003-08-18 Marcus Brinkmann <marcus@g10code.de>
+
+ * funopen.c, putc_unlocked.c, isascii.c, memrchr.c: New files.
+ * fopencookie.c: File removed.
+
2003-08-15 Marcus Brinkmann <marcus@g10code.de>
* gpgme-config.in: Put gpg-error related flags after gpgme's.
--- /dev/null
+/* funopen.c - Replacement for funopen.
+ * Copyright (C) 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef HAVE_FOPENCOOKIE
+FILE *
+funopen(const void *cookie, cookie_read_function_t *readfn,
+ cookie_write_function_t *writefn,
+ cookie_seek_function_t *seekfn,
+ cookie_close_function_t *closefn)
+{
+ cookie_io_functions_t io = { read: readfn, write: writefn,
+ seek: seekfn,
+ close: closefn };
+
+ return fopencookie ((void *) cookie,
+ readfn ? ( writefn ? "rw" : "r" )
+ : ( writefn ? "w" : ""), io);
+}
+#else
+#error No known way to implement funopen.
+#endif
AM_PATH_GPGME macro) check that this header matches the installed
library. Warning: Do not edit the next line. configure will do
that for you! */
-#define GPGME_VERSION "0.4.2"
+#define GPGME_VERSION "0.4.3"
\f
/* Some opaque data types used by GPGME. */
--- /dev/null
+/* isascii.c - Replacement for isascii.
+ * Copyright (C) 2002 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+int
+isascii (int c)
+{
+ return (((c) & ~0x7f) == 0);
+}
--- /dev/null
+/* memrchr.c - Replacement for memrchr.
+ * Copyright (C) 2002 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+
+void *
+memrchr (const void *block, int c, size_t size)
+{
+ void *p;
+
+ for (p = block + size; p != block; p --)
+ if (*p == c)
+ return p;
+ return 0;
+}
-/* fopencookie.c - Dummy glibc replacement
+/* putc_unlocked.c - Replacement for putc_unlocked.
* Copyright (C) 2002 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
-#include <stdio.h>
-#include <errno.h>
-#include "util.h"
+#include <stdio.h>
-FILE *
-fopencookie (void *cookie, const char *opentype,
- cookie_io_functions_t funclist)
+int
+putc_unlocked (int c, FILE *stream)
{
- errno = ENOSYS;
- return NULL;
+ return putc (c, stream);
}
-
-