From c93237c3a4cb4ecc579033c31a56cf447c277be3 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann Date: Mon, 18 Aug 2003 19:17:08 +0000 Subject: [PATCH] 2003-08-18 Marcus Brinkmann * configure.ac: If building Assuan, check for funopen and fopencookie, and make isascii, putc_unlocked and memrchr replacement functions. assuan/ Update to the latest assuan version. gpgme/ 2003-08-18 Marcus Brinkmann * funopen.c, putc_unlocked.c, isascii.c, memrchr.c: New files. * fopencookie.c: File removed. --- ChangeLog | 6 + assuan/ChangeLog | 211 +++++++++- assuan/Makefile.am | 8 +- assuan/README.1st | 4 +- assuan/assuan-buffer.c | 216 ++++++----- assuan/assuan-defs.h | 67 +++- assuan/assuan-domain-connect.c | 473 +++++++++++++++++++++++ assuan/assuan-domain-server.c | 46 +++ assuan/assuan-handler.c | 161 ++++---- assuan/assuan-inquire.c | 7 +- assuan/assuan-io.c | 31 +- assuan/assuan-listen.c | 2 +- assuan/assuan-logging.c | 42 ++ assuan/assuan-pipe-connect.c | 68 ++-- assuan/assuan-pipe-server.c | 11 +- assuan/assuan-socket-connect.c | 67 ++-- assuan/assuan-socket-server.c | 9 +- assuan/assuan-util.c | 15 +- assuan/assuan.h | 67 +++- assuan/mkerrors | 15 +- configure.ac | 53 +-- gpgme/ChangeLog | 5 + gpgme/funopen.c | 44 +++ gpgme/gpgme.h | 2 +- gpgme/isascii.c | 29 ++ gpgme/memrchr.c | 36 ++ gpgme/{fopencookie.c => putc_unlocked.c} | 16 +- 27 files changed, 1325 insertions(+), 386 deletions(-) create mode 100644 assuan/assuan-domain-connect.c create mode 100644 assuan/assuan-domain-server.c create mode 100644 assuan/assuan-logging.c create mode 100644 gpgme/funopen.c create mode 100644 gpgme/isascii.c create mode 100644 gpgme/memrchr.c rename gpgme/{fopencookie.c => putc_unlocked.c} (79%) diff --git a/ChangeLog b/ChangeLog index ba2b243..676701c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2003-08-18 Marcus Brinkmann + + * configure.ac: If building Assuan, check for funopen and + fopencookie, and make isascii, putc_unlocked and memrchr + replacement functions. + 2003-07-31 Marcus Brinkmann * configure.ac (AC_INIT): Bump version to 0.4.3. diff --git a/assuan/ChangeLog b/assuan/ChangeLog index 85dc5ef..3d2faf9 100644 --- a/assuan/ChangeLog +++ b/assuan/ChangeLog @@ -1,3 +1,209 @@ +2003-08-13 Werner Koch + + * assuan-inquire.c (assuan_inquire): Increase length of cmdbuf to + the Assuan limit. + +2003-06-24 Werner Koch + + * mkerrors: Kludge to print libgpg-error values in an easier + readable way. + +2003-04-29 Werner Koch + + * 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 + + * Makefile.am (bin_SCRIPTS): Renamed from bin_PROGRAMS. + +2003-02-18 Neal H. Walfield + + * 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 + + * 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 + + * libassuan-config.in: New file. + * Makefile.am (bin_PROGRAMS): New variable. + +2003-02-17 Neal H. Walfield + + * .cvsignore: New file. + +2003-02-17 Neal H. Walfield + + * 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 + + * 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 + + * 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 + + * 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 + + * assuan.h: Add prototype for assuan_domain_connect and + assuan_init_domain_server. + * assuan-defs.h: Include . + 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 + + * 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 + + * assuan-buffer.c (readline): Use memrchr. + (_assuan_read_line): Rewritten to use the string functions. + +2002-11-20 Neal H. Walfield + + * 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 + + * 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 . + (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 * assuan-pipe-connect.c (assuan_pipe_connect): Changed the order @@ -267,11 +473,6 @@ * 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 diff --git a/assuan/Makefile.am b/assuan/Makefile.am index 57c95fa..db29d18 100644 --- a/assuan/Makefile.am +++ b/assuan/Makefile.am @@ -1,5 +1,5 @@ # 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. # @@ -43,8 +43,10 @@ libassuan_la_SOURCES = \ 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 diff --git a/assuan/README.1st b/assuan/README.1st index bb52959..b7d5311 100644 --- a/assuan/README.1st +++ b/assuan/README.1st @@ -1 +1,3 @@ -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. diff --git a/assuan/assuan-buffer.c b/assuan/assuan-buffer.c index 8017183..59518f2 100644 --- a/assuan/assuan-buffer.c +++ b/assuan/assuan-buffer.c @@ -1,5 +1,5 @@ /* 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. * @@ -27,28 +27,12 @@ #include #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) { @@ -62,9 +46,10 @@ writen ( int fd, const char *buffer, size_t length ) 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; @@ -73,7 +58,7 @@ readline (int fd, char *buf, size_t buflen, int *r_nread, int *eof) *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) { @@ -90,10 +75,9 @@ readline (int fd, char *buf, size_t buflen, int *r_nread, int *eof) 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 */ } @@ -105,8 +89,9 @@ int _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; @@ -116,86 +101,92 @@ _assuan_read_line (ASSUAN_CONTEXT ctx) { 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; + } } @@ -233,7 +224,7 @@ assuan_pending_line (ASSUAN_CONTEXT ctx) AssuanError -assuan_write_line (ASSUAN_CONTEXT ctx, const char *line ) +assuan_write_line (ASSUAN_CONTEXT ctx, const char *line) { int rc; size_t len; @@ -250,22 +241,23 @@ assuan_write_line (ASSUAN_CONTEXT ctx, const char *line ) /* 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; } @@ -322,7 +314,9 @@ _assuan_cookie_write_data (void *cookie, const char *buffer, size_t size) { 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 @@ -333,7 +327,7 @@ _assuan_cookie_write_data (void *cookie, const char *buffer, size_t size) } *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; @@ -366,19 +360,19 @@ _assuan_cookie_write_flush (void *cookie) 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; @@ -432,3 +426,23 @@ assuan_send_data (ASSUAN_CONTEXT ctx, const void *buffer, size_t length) 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); +} diff --git a/assuan/assuan-defs.h b/assuan/assuan-defs.h index f885869..1f7f1f0 100644 --- a/assuan/assuan-defs.h +++ b/assuan/assuan-defs.h @@ -22,17 +22,34 @@ #define ASSUAN_DEFS_H #include +#include +#include +#include + #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*/ @@ -81,6 +98,23 @@ struct assuan_context_s { 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); @@ -99,14 +133,21 @@ struct assuan_context_s { 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); @@ -137,11 +178,17 @@ void _assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length); 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*/ diff --git a/assuan/assuan-domain-connect.c b/assuan/assuan-domain-connect.c new file mode 100644 index 0000000..49dcb55 --- /dev/null +++ b/assuan/assuan-domain-connect.c @@ -0,0 +1,473 @@ +/* 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 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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; +} diff --git a/assuan/assuan-domain-server.c b/assuan/assuan-domain-server.c new file mode 100644 index 0000000..b62b140 --- /dev/null +++ b/assuan/assuan-domain-server.c @@ -0,0 +1,46 @@ +/* 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 +#endif + +#include + +#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; +} diff --git a/assuan/assuan-handler.c b/assuan/assuan-handler.c index 6ddfe88..f8b85db 100644 --- a/assuan/assuan-handler.c +++ b/assuan/assuan-handler.c @@ -1,5 +1,5 @@ /* 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. * @@ -25,27 +25,12 @@ #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); @@ -149,25 +134,32 @@ std_handler_end (ASSUAN_CONTEXT ctx, char *line) 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= 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[=] 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= */ @@ -176,7 +168,7 @@ std_handler_input (ASSUAN_CONTEXT ctx, char *line) { 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; @@ -191,7 +183,7 @@ std_handler_output (ASSUAN_CONTEXT ctx, char *line) { 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; @@ -205,25 +197,24 @@ std_handler_output (ASSUAN_CONTEXT ctx, char *line) /* 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 } }; @@ -231,54 +222,46 @@ static struct { /** * 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; @@ -299,7 +282,6 @@ assuan_register_command (ASSUAN_CONTEXT ctx, } 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; @@ -374,8 +356,7 @@ _assuan_register_std_commands (ASSUAN_CONTEXT ctx) { 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; } @@ -624,17 +605,13 @@ assuan_get_active_fds (ASSUAN_CONTEXT ctx, int what, 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; } diff --git a/assuan/assuan-inquire.c b/assuan/assuan-inquire.c index 197e210..ec9d8e6 100644 --- a/assuan/assuan-inquire.c +++ b/assuan/assuan-inquire.c @@ -1,5 +1,5 @@ /* 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. * @@ -31,7 +31,8 @@ #define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1)) -struct membuf { +struct membuf +{ size_t len; size_t size; char *buf; @@ -139,7 +140,7 @@ assuan_inquire (ASSUAN_CONTEXT ctx, const char *keyword, { 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; diff --git a/assuan/assuan-io.c b/assuan/assuan-io.c index 135cb02..b10571b 100644 --- a/assuan/assuan-io.c +++ b/assuan/assuan-io.c @@ -1,4 +1,4 @@ -/* 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. @@ -18,6 +18,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ +#include "assuan-defs.h" #include #include @@ -28,33 +29,13 @@ extern ssize_t pth_write (int fd, const void *buffer, size_t size); #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); } diff --git a/assuan/assuan-listen.c b/assuan/assuan-listen.c index 3d4ee5f..aae3f7b 100644 --- a/assuan/assuan-listen.c +++ b/assuan/assuan-listen.c @@ -54,7 +54,7 @@ assuan_set_hello_line (ASSUAN_CONTEXT ctx, const char *line) * 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. * diff --git a/assuan/assuan-logging.c b/assuan/assuan-logging.c new file mode 100644 index 0000000..340ce72 --- /dev/null +++ b/assuan/assuan-logging.c @@ -0,0 +1,42 @@ +/* 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 + +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 ""; +} diff --git a/assuan/assuan-pipe-connect.c b/assuan/assuan-pipe-connect.c index d7595c9..d30c106 100644 --- a/assuan/assuan-pipe-connect.c +++ b/assuan/assuan-pipe-connect.c @@ -1,5 +1,5 @@ /* 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. * @@ -40,17 +40,13 @@ #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) { @@ -174,21 +170,21 @@ assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name, char *const argv[], /* 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. */ @@ -203,15 +199,15 @@ assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name, char *const argv[], 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 @@ -253,13 +249,11 @@ assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name, char *const argv[], 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; } } diff --git a/assuan/assuan-pipe-server.c b/assuan/assuan-pipe-server.c index 82bb322..ba269b0 100644 --- a/assuan/assuan-pipe-server.c +++ b/assuan/assuan-pipe-server.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "assuan-defs.h" @@ -44,12 +45,15 @@ finish_connection (ASSUAN_CONTEXT ctx) 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; @@ -62,10 +66,11 @@ _assuan_new_context (ASSUAN_CONTEXT *r_ctx) 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; @@ -116,7 +121,7 @@ assuan_deinit_server (ASSUAN_CONTEXT ctx) 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); diff --git a/assuan/assuan-socket-connect.c b/assuan/assuan-socket-connect.c index 64a22bf..a7246cc 100644 --- a/assuan/assuan-socket-connect.c +++ b/assuan/assuan-socket-connect.c @@ -1,5 +1,5 @@ /* 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. * @@ -29,20 +29,10 @@ #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) @@ -61,16 +51,16 @@ do_deinit (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; @@ -95,30 +85,31 @@ assuan_socket_connect (ASSUAN_CONTEXT *r_ctx, 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 */ { @@ -126,15 +117,13 @@ assuan_socket_connect (ASSUAN_CONTEXT *r_ctx, 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; } } @@ -146,5 +135,3 @@ assuan_socket_connect (ASSUAN_CONTEXT *r_ctx, *r_ctx = ctx; return 0; } - - diff --git a/assuan/assuan-socket-server.c b/assuan/assuan-socket-server.c index bfa9cfa..8d23a6b 100644 --- a/assuan/assuan-socket-server.c +++ b/assuan/assuan-socket-server.c @@ -98,7 +98,8 @@ deinit_socket_server (ASSUAN_CONTEXT ctx) 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 */ @@ -125,6 +126,8 @@ assuan_init_socket_server (ASSUAN_CONTEXT *r_ctx, int listen_fd) ctx->accept_handler = accept_connection; ctx->finish_handler = finish_connection; + ctx->io = &io; + rc = _assuan_register_std_commands (ctx); if (rc) xfree (ctx); @@ -145,13 +148,15 @@ assuan_init_connected_socket_server (ASSUAN_CONTEXT *r_ctx, int fd) 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; diff --git a/assuan/assuan-util.c b/assuan/assuan-util.c index 76f7f06..fc0beed 100644 --- a/assuan/assuan-util.c +++ b/assuan/assuan-util.c @@ -1,5 +1,5 @@ /* 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. * @@ -26,10 +26,6 @@ #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; @@ -159,18 +155,13 @@ _assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length) } } - /* 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; @@ -226,5 +217,3 @@ _assuan_log_sanitized_string (const char *string) funlockfile (fp); #endif } - - diff --git a/assuan/assuan.h b/assuan/assuan.h index d8b874e..f898c26 100644 --- a/assuan/assuan.h +++ b/assuan/assuan.h @@ -1,5 +1,5 @@ /* 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. * @@ -23,21 +23,20 @@ #include #include -#include /* for ssize_t */ +#include #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, @@ -105,7 +104,8 @@ typedef enum { } 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, @@ -127,7 +127,7 @@ typedef struct assuan_context_s *ASSUAN_CONTEXT; /*-- 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)); @@ -155,6 +155,12 @@ AssuanError assuan_set_okay_line (ASSUAN_CONTEXT ctx, const char *line); 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); @@ -181,6 +187,26 @@ AssuanError assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name, 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); @@ -209,6 +235,12 @@ AssuanError assuan_write_line (ASSUAN_CONTEXT ctx, const char *line ); 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), @@ -225,8 +257,21 @@ void assuan_end_confidential (ASSUAN_CONTEXT ctx); /*-- 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 */ diff --git a/assuan/mkerrors b/assuan/mkerrors index d0c59ff..1112941 100755 --- a/assuan/mkerrors +++ b/assuan/mkerrors @@ -40,7 +40,7 @@ const char * assuan_strerror (AssuanError err) { const char *s; - static char buf[25]; + static char buf[50]; switch (err) { @@ -62,7 +62,18 @@ printf "%s\"; break;\n", tolower(substr(s,8)); ' cat <> 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; diff --git a/configure.ac b/configure.ac index 7b70d09..1515a0c 100644 --- a/configure.ac +++ b/configure.ac @@ -77,8 +77,8 @@ AC_SUBST(VERSION) 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 @@ -125,38 +125,31 @@ case "${host}" in 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) @@ -164,17 +157,11 @@ if test "$ac_cv_func_vasprintf" != yes; then 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]), @@ -235,9 +222,25 @@ AM_CONDITIONAL(HAVE_GPGSM, [test -n "$GPGSM" && test -r "$GPGSM"]) 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. diff --git a/gpgme/ChangeLog b/gpgme/ChangeLog index 94dd842..34667d2 100644 --- a/gpgme/ChangeLog +++ b/gpgme/ChangeLog @@ -1,3 +1,8 @@ +2003-08-18 Marcus Brinkmann + + * funopen.c, putc_unlocked.c, isascii.c, memrchr.c: New files. + * fopencookie.c: File removed. + 2003-08-15 Marcus Brinkmann * gpgme-config.in: Put gpg-error related flags after gpgme's. diff --git a/gpgme/funopen.c b/gpgme/funopen.c new file mode 100644 index 0000000..e768b05 --- /dev/null +++ b/gpgme/funopen.c @@ -0,0 +1,44 @@ +/* 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 +#endif + +#include + +#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 diff --git a/gpgme/gpgme.h b/gpgme/gpgme.h index ed1d25b..6c6c97e 100644 --- a/gpgme/gpgme.h +++ b/gpgme/gpgme.h @@ -63,7 +63,7 @@ extern "C" { 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" /* Some opaque data types used by GPGME. */ diff --git a/gpgme/isascii.c b/gpgme/isascii.c new file mode 100644 index 0000000..565c716 --- /dev/null +++ b/gpgme/isascii.c @@ -0,0 +1,29 @@ +/* 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 +#endif + +int +isascii (int c) +{ + return (((c) & ~0x7f) == 0); +} diff --git a/gpgme/memrchr.c b/gpgme/memrchr.c new file mode 100644 index 0000000..3e60c55 --- /dev/null +++ b/gpgme/memrchr.c @@ -0,0 +1,36 @@ +/* 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 +#endif + +#include + +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; +} diff --git a/gpgme/fopencookie.c b/gpgme/putc_unlocked.c similarity index 79% rename from gpgme/fopencookie.c rename to gpgme/putc_unlocked.c index 7862b9a..02c6461 100644 --- a/gpgme/fopencookie.c +++ b/gpgme/putc_unlocked.c @@ -1,4 +1,4 @@ -/* 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. @@ -21,17 +21,11 @@ #ifdef HAVE_CONFIG_H #include #endif -#include -#include -#include "util.h" +#include -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); } - - -- 2.26.2