diff options
| -rw-r--r-- | ChangeLog | 6 | ||||
| -rw-r--r-- | assuan/ChangeLog | 211 | ||||
| -rw-r--r-- | assuan/Makefile.am | 8 | ||||
| -rw-r--r-- | assuan/README.1st | 4 | ||||
| -rw-r--r-- | assuan/assuan-buffer.c | 216 | ||||
| -rw-r--r-- | assuan/assuan-defs.h | 67 | ||||
| -rw-r--r-- | assuan/assuan-domain-connect.c | 473 | ||||
| -rw-r--r-- | assuan/assuan-domain-server.c | 46 | ||||
| -rw-r--r-- | assuan/assuan-handler.c | 161 | ||||
| -rw-r--r-- | assuan/assuan-inquire.c | 7 | ||||
| -rw-r--r-- | assuan/assuan-io.c | 31 | ||||
| -rw-r--r-- | assuan/assuan-listen.c | 2 | ||||
| -rw-r--r-- | assuan/assuan-logging.c | 42 | ||||
| -rw-r--r-- | assuan/assuan-pipe-connect.c | 68 | ||||
| -rw-r--r-- | assuan/assuan-pipe-server.c | 11 | ||||
| -rw-r--r-- | assuan/assuan-socket-connect.c | 67 | ||||
| -rw-r--r-- | assuan/assuan-socket-server.c | 9 | ||||
| -rw-r--r-- | assuan/assuan-util.c | 15 | ||||
| -rw-r--r-- | assuan/assuan.h | 67 | ||||
| -rwxr-xr-x | assuan/mkerrors | 15 | ||||
| -rw-r--r-- | configure.ac | 53 | ||||
| -rw-r--r-- | gpgme/ChangeLog | 5 | ||||
| -rw-r--r-- | gpgme/funopen.c | 44 | ||||
| -rw-r--r-- | gpgme/gpgme.h | 2 | ||||
| -rw-r--r-- | gpgme/isascii.c | 29 | ||||
| -rw-r--r-- | gpgme/memrchr.c | 36 | ||||
| -rw-r--r-- | gpgme/putc_unlocked.c (renamed from gpgme/fopencookie.c) | 16 | 
27 files changed, 1325 insertions, 386 deletions
| @@ -1,3 +1,9 @@ +2003-08-18  Marcus Brinkmann  <[email protected]> + +	* configure.ac: If building Assuan, check for funopen and +	fopencookie, and make isascii, putc_unlocked and memrchr +	replacement functions. +  2003-07-31  Marcus Brinkmann  <[email protected]>  	* configure.ac (AC_INIT): Bump version to 0.4.3. diff --git a/assuan/ChangeLog b/assuan/ChangeLog index 85dc5ef8..3d2faf92 100644 --- a/assuan/ChangeLog +++ b/assuan/ChangeLog @@ -1,3 +1,209 @@ +2003-08-13  Werner Koch  <[email protected]> + +	* assuan-inquire.c (assuan_inquire): Increase length of cmdbuf to +	the Assuan limit. + +2003-06-24  Werner Koch  <[email protected]> + +	* mkerrors: Kludge to print libgpg-error values in an easier +	readable way. + +2003-04-29  Werner Koch  <[email protected]> + +	* 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  <[email protected]> + +	* Makefile.am (bin_SCRIPTS): Renamed from bin_PROGRAMS. + +2003-02-18  Neal H. Walfield  <[email protected]> + +	* 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  <[email protected]> + +	* 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  <[email protected]> + +	* libassuan-config.in: New file. +	* Makefile.am (bin_PROGRAMS): New variable. + +2003-02-17  Neal H. Walfield  <[email protected]> + +	* .cvsignore: New file. + +2003-02-17  Neal H. Walfield  <[email protected]> + +	* 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  <[email protected]> + +	* 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  <[email protected]> + +	* 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  <[email protected]> + +	* 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  <[email protected]> + +	* 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  <[email protected]> + +	* 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  <[email protected]> + +	* assuan-buffer.c (readline): Use memrchr. +	(_assuan_read_line): Rewritten to use the string functions. + +2002-11-20  Neal H. Walfield  <[email protected]> + +	* 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  <[email protected]> + +	* 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  <[email protected]>  	* 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 57c95fa3..db29d187 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 bb52959c..b7d53112 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 8017183e..59518f25 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 <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)          { @@ -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 f8858692..1f7f1f03 100644 --- a/assuan/assuan-defs.h +++ b/assuan/assuan-defs.h @@ -22,17 +22,34 @@  #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*/ @@ -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 00000000..49dcb557 --- /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 <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; +} diff --git a/assuan/assuan-domain-server.c b/assuan/assuan-domain-server.c new file mode 100644 index 00000000..b62b140d --- /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 <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; +} diff --git a/assuan/assuan-handler.c b/assuan/assuan-handler.c index 6ddfe889..f8b85dbb 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=<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> */ @@ -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 197e2101..ec9d8e65 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 135cb02d..b10571be 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 <sys/types.h>  #include <unistd.h> @@ -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 3d4ee5f6..aae3f7b7 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 00000000..340ce724 --- /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 <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 ""; +} diff --git a/assuan/assuan-pipe-connect.c b/assuan/assuan-pipe-connect.c index d7595c9f..d30c106b 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 82bb3228..ba269b04 100644 --- a/assuan/assuan-pipe-server.c +++ b/assuan/assuan-pipe-server.c @@ -21,6 +21,7 @@  #include <config.h>  #include <stdlib.h>  #include <stdio.h> +#include <unistd.h>  #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 64a22bf5..a7246ccf 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 bfa9cfa7..8d23a6bd 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 76f7f065..fc0beedb 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 d8b874eb..f898c260 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 <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, @@ -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 d0c59ff3..11129419 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 <<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; diff --git a/configure.ac b/configure.ac index 7b70d09d..1515a0c6 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 94dd842b..34667d27 100644 --- a/gpgme/ChangeLog +++ b/gpgme/ChangeLog @@ -1,3 +1,8 @@ +2003-08-18  Marcus Brinkmann  <[email protected]> + +	* funopen.c, putc_unlocked.c, isascii.c, memrchr.c: New files. +	* fopencookie.c: File removed. +  2003-08-15  Marcus Brinkmann  <[email protected]>  	* 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 00000000..e768b057 --- /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 <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 diff --git a/gpgme/gpgme.h b/gpgme/gpgme.h index ed1d25bb..6c6c97e0 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 00000000..565c7166 --- /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 <config.h> +#endif + +int +isascii (int c) +{ +  return (((c) & ~0x7f) == 0); +} diff --git a/gpgme/memrchr.c b/gpgme/memrchr.c new file mode 100644 index 00000000..3e60c55e --- /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 <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; +} diff --git a/gpgme/fopencookie.c b/gpgme/putc_unlocked.c index 7862b9a0..02c64613 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 <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);  } - - | 
