2003-08-18 Marcus Brinkmann <marcus@g10code.de>
authorMarcus Brinkmann <mb@g10code.com>
Mon, 18 Aug 2003 19:17:08 +0000 (19:17 +0000)
committerMarcus Brinkmann <mb@g10code.com>
Mon, 18 Aug 2003 19:17:08 +0000 (19:17 +0000)
* 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  <marcus@g10code.de>

* funopen.c, putc_unlocked.c, isascii.c, memrchr.c: New files.
* fopencookie.c: File removed.

27 files changed:
ChangeLog
assuan/ChangeLog
assuan/Makefile.am
assuan/README.1st
assuan/assuan-buffer.c
assuan/assuan-defs.h
assuan/assuan-domain-connect.c [new file with mode: 0644]
assuan/assuan-domain-server.c [new file with mode: 0644]
assuan/assuan-handler.c
assuan/assuan-inquire.c
assuan/assuan-io.c
assuan/assuan-listen.c
assuan/assuan-logging.c [new file with mode: 0644]
assuan/assuan-pipe-connect.c
assuan/assuan-pipe-server.c
assuan/assuan-socket-connect.c
assuan/assuan-socket-server.c
assuan/assuan-util.c
assuan/assuan.h
assuan/mkerrors
configure.ac
gpgme/ChangeLog
gpgme/funopen.c [new file with mode: 0644]
gpgme/gpgme.h
gpgme/isascii.c [new file with mode: 0644]
gpgme/memrchr.c [new file with mode: 0644]
gpgme/putc_unlocked.c [moved from gpgme/fopencookie.c with 79% similarity]

index ba2b243..676701c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2003-08-18  Marcus Brinkmann  <marcus@g10code.de>
+
+       * configure.ac: If building Assuan, check for funopen and
+       fopencookie, and make isascii, putc_unlocked and memrchr
+       replacement functions.
+
 2003-07-31  Marcus Brinkmann  <marcus@g10code.de>
 
        * configure.ac (AC_INIT): Bump version to 0.4.3.
index 85dc5ef..3d2faf9 100644 (file)
@@ -1,3 +1,209 @@
+2003-08-13  Werner Koch  <wk@gnupg.org>
+
+       * assuan-inquire.c (assuan_inquire): Increase length of cmdbuf to
+       the Assuan limit.
+
+2003-06-24  Werner Koch  <wk@gnupg.org>
+
+       * mkerrors: Kludge to print libgpg-error values in an easier
+       readable way.
+
+2003-04-29  Werner Koch  <wk@gnupg.org>
+
+       * libassuan.m4: New. Based on libgrypt.m4.
+       * Makefile.am (m4data_DATA): New.
+
+       * assuan.h (AssuanCommand): Removed.
+
+       * assuan-handler.c: Remove the cmd_id element,
+       (assuan_register_command): Likewise.  Note that semantics changed.
+       (_assuan_register_std_commands): Adjusted.
+
+2003-02-22  Neal H. Walfield  <neal@g10code.de>
+
+       * Makefile.am (bin_SCRIPTS): Renamed from bin_PROGRAMS.
+
+2003-02-18  Neal H. Walfield  <neal@g10code.de>
+
+       * Makefile.am (libassuan_a_LIBADD): New variable.
+       * funopen.c: Move from ../common.
+       * isascii.c: Likewise.
+       * memrchr.c: Likewise.
+       * putc_unlocked.c: Likewise.
+       
+2003-02-18  Neal H. Walfield  <neal@g10code.de>
+
+       * assuan-handler.c (_IO_cookie_io_functions_t): Remove.
+       (cookie_io_functions_t): Remove.
+       (fopencookie): Remove prototype.
+       (assuan_get_data_fp): Use funopen, not fopencookie.
+
+2003-02-18  Neal H. Walfield  <neal@g10code.de>
+
+       * libassuan-config.in: New file.
+       * Makefile.am (bin_PROGRAMS): New variable.
+
+2003-02-17  Neal H. Walfield  <neal@g10code.de>
+
+       * .cvsignore: New file.
+
+2003-02-17  Neal H. Walfield  <neal@g10code.de>
+
+       * Makefile.am (lib_LIBRARIES): Use this instead of . . .
+       (noinst_LIBRARIES): . . . this.
+       (include_HEADERS): New variable.
+       (libassuan_a_SOURCES): Remove assuan.h, add assuan-logging.c.
+
+       * assuan.h (assuan_set_assuan_log_stream): New prototype.
+       (assuan_get_assuan_log_stream): Likewise.
+       (assuan_get_assuan_log_prefix): Likewise.
+       * assuan-logging.c: New file.
+
+       * assuan-buffer.c [HAVE_JNLIB_LOGGIN]: Do not include
+       "../jnlib/logging.h".
+       (my_log_prefix): Remove function.
+       (_assuan_read_line): Use assuan_get_assuan_log_prefix in lieu of
+       my_log_prefix.
+       (assuan_write_line): Likewise.
+       (_assuan_cookie_write_data): Likewise.
+       (_assuan_cookie_write_flush): Likewise.
+       * assuan-domain-connect.c (LOGERROR, LOGERROR1, LOGERROR2,
+       LOGERRORX):  Remove.
+       (LOG): New macro.
+       (domain_reader): Use it.
+       (domain_writer): Likewise.
+       (domain_sendfd): Likewise.
+       (domain_receivefd): Likewise.
+       (_assuan_domain_init): Likewise.
+       (assuan_domain_connect): Likewise.
+       * assuan-pipe-connect.c [HAVE_JNLIB_LOGGIN]: Do not include
+       "../jnlib/logging.h".
+       (LOGERROR, LOGERROR1, LOGERROR2, LOGERRORX):  Remove.
+       (LOG): New macro.
+       (assuan_pipe_connect): Use it.
+       * assuan-socket-connect.c [HAVE_JNLIB_LOGGIN]: Do not include
+       "../jnlib/logging.h".
+       (LOGERROR, LOGERROR1, LOGERROR2, LOGERRORX):  Remove.
+       (LOG): New macro.
+       (assuan_socket_connect): Use it.
+       (socket_reader): Remove dead code.
+       (socket_writer): Likewise.
+       * assuan-util.c [HAVE_JNLIB_LOGGIN]: Do not include
+       "../jnlib/logging.h".
+       (_assuan_log_sanitized_string): Use assuan_get_assuan_log_stream,
+       not jnlib.
+
+2002-11-24  Neal H. Walfield  <neal@g10code.de>
+
+       * assuan.h (assuan_command_parse_fd): New prototype.
+       * assuan-handler.c (assuan_command_parse_fd): Rename from
+       parse_cmd_input_output.  Export.
+       (std_handler_input): Update to use assuan_command_parse_fd.
+       (std_handler_output): Likewise.
+
+2002-11-24  Neal H. Walfield  <neal@g10code.de>
+
+       * assuan.h (assuan_sendfd): New prototype.
+       (assuan_receivefd): New prototype.
+       * assuan-buffer.c (assuan_sendfd): New function.
+       (assuan_receivefd): New function.
+       * assuan-handler.c (parse_cmd_input_output): Recognize incoming
+       file descriptors and act appropriately.
+       * assuan-defs.h (struct assuan_io): Add fields sendfd and
+       receivefd.
+       (struct assuan_context_s): Add fields pendingfds and
+       pendingfdscount.
+       * assuan-pipe-server.c (_assuan_new_context): Update IO to reflect
+       new features.
+       * assuan-domain-connect.c (do_deinit): Cleanup any unreceived file
+       descriptors.
+       (domain_reader): Receive file descriptors.
+       (domain_sendfd): New function.
+       (domain_receivefd): New function.
+       (_assuan_domain_init): Update initialization code to reflect new
+       features.
+
+2002-11-24  Neal H. Walfield  <neal@g10code.de>
+
+       * assuan-domain-connect.c (do_finish): Remove.
+       (_assuan_domain_init): Use default handlers where possible.
+       Add an assert and update comments.
+       * assuan-domain-server.c (accept_connection): Remove.
+       (assuan_init_domain_server): Use default handlers where possible.
+       Put the server in pipe mode: it can only be used by a single
+       client.
+
+2002-11-24  Neal H. Walfield  <neal@g10code.de>
+
+       * assuan.h: Add prototype for assuan_domain_connect and
+       assuan_init_domain_server.
+       * assuan-defs.h: Include <unistd.h>.
+       Add prototype for _assuan_domain_init.
+       * assuan-domain-connect.c: New file.
+       * assuan-domain-server.c: New file.
+       * Makefile.am (libassuan_a_SOURCES): Add assuan-domain-connect.c
+       and assuan-domain-server.c
+
+2002-11-23  Neal H. Walfield  <neal@g10code.de>
+
+       * Makefile.am (libassuan_a_SOURCES): Add assuan-io.c.
+       * assuan-io.c: Restore.
+       (_assuan_simple_read): Rename from _assuan_read.
+       (_assuan_simple_write): Rename from _assuan_write.
+       * assuan-defs.h (_assuan_simple_read): New prototype.
+       (_assuan_simple_write): Likewise.
+       * assuan-pipe-server.c (pipe_reader): Remove.
+       (pipe_writer): Remove.
+       (_assuan_new_context): Initialize IO is with _assuan_simple_read
+       and _assuan_simple_write.
+       * assuan-socket-connect.c (socket_reader): Remove.
+       (socket_writer): Remove.
+       (assuan_socket_connect): Initialize IO is with _assuan_simple_read
+       and _assuan_simple_write.
+       * assuan-socket-server.c (io): New local variable.
+       (assuan_init_socket_server): Initialize CTX->io.
+       (assuan_init_connected_socket_server): Likewise.
+
+2002-11-23  Neal H. Walfield  <neal@g10code.de>
+
+       * assuan-buffer.c (readline): Use memrchr.
+       (_assuan_read_line): Rewritten to use the string functions.
+
+2002-11-20  Neal H. Walfield  <neal@g10code.de>
+
+       * assuan-socket-connect.c (assuan_socket_connect): Pass PF_LOCAL
+       to socket(), not AF_UNIX: it expects a PF_* macro and the former
+       is more portable.
+       (assuan_socket_connect): Use AF_LOCAL, not AF_UNIX which is more
+       POSIXy.
+
+2002-11-20  Neal H. Walfield  <neal@g10code.de>
+
+       * assuan-defs.h (struct assuan_io): New structure.
+       (struct assuan_context_s): New field, io.
+       (_assuan_read): Depreciated.
+       (_assuan_write): Likewise.
+       * assuan-pipe-server.c: Include <unistd.h>.
+       (pipe_reader): New function.
+       (pipe_writer): Likewise.
+       (_assuan_new_context.IO): New local static.  Set to pipe_reader
+       and pipe_writer.  Use it to initialize new context.
+       * assuan-socket-connect.c (socket_reader): New function.
+       (socket_writer): New function.
+       (assuan_socket_connect.IO): New local static.  Set to socket_reader
+       and socket_writer.  Use it to initialize new context.
+       * assuan-buffer.c (writen): Take an ASSUAN_CONTEXT rather than a
+       file descriptor.  Do not use _assuan_write but the write method
+       in the supplied context.
+       (readline): Likewise for _assuan_read.
+       (assuan_write_line): When calling writen, pass CTX; not the file
+       descriptor directly.
+       (_assuan_cookie_write_data): Likewise.
+       (_assuan_cookie_write_flush): Likewise.
+       (_assuan_read_line): Likewise for readline.
+       * Makefile.am (libassuan_a_SOURCES): Remove assuan-io.c.
+       * assuan-io.c: Removed.
+
 2002-11-10  Werner Koch  <wk@gnupg.org>
 
        * assuan-pipe-connect.c (assuan_pipe_connect): Changed the order
        * assuan-defs.h: Add space in the context for this.
 
        
-     ***********************************************************
-     * Please note that Assuan is maintained as part of GnuPG. *
-     * You may find it source-copied in other packages.        *
-     ***********************************************************       
-       
  Copyright 2001, 2002 Free Software Foundation, Inc.
 
  This file is free software; as a special exception the author gives
index 57c95fa..db29d18 100644 (file)
@@ -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
index bb52959..b7d5311 100644 (file)
@@ -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.
index 8017183..59518f2 100644 (file)
@@ -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.
  *
 #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);
+}
index f885869..1f7f1f0 100644 (file)
 #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 (file)
index 0000000..49dcb55
--- /dev/null
@@ -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 (file)
index 0000000..b62b140
--- /dev/null
@@ -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;
+}
index 6ddfe88..f8b85db 100644 (file)
@@ -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.
  *
 
 #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;
 }
index 197e210..ec9d8e6 100644 (file)
@@ -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;
index 135cb02..b10571b 100644 (file)
@@ -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);
 }
index 3d4ee5f..aae3f7b 100644 (file)
@@ -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 (file)
index 0000000..340ce72
--- /dev/null
@@ -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 "";
+}
index d7595c9..d30c106 100644 (file)
@@ -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.
  *
 #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;
       }
   }
 
index 82bb322..ba269b0 100644 (file)
@@ -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);
index 64a22bf..a7246cc 100644 (file)
@@ -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.
  *
 
 #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;
 }
-
-
index bfa9cfa..8d23a6b 100644 (file)
@@ -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;
index 76f7f06..fc0beed 100644 (file)
@@ -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.
  *
 
 #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
 }
-
-
index d8b874e..f898c26 100644 (file)
@@ -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.
  *
 
 #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 */
index d0c59ff..1112941 100755 (executable)
@@ -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;
index 7b70d09..1515a0c 100644 (file)
@@ -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.
index 94dd842..34667d2 100644 (file)
@@ -1,3 +1,8 @@
+2003-08-18  Marcus Brinkmann  <marcus@g10code.de>
+
+       * funopen.c, putc_unlocked.c, isascii.c, memrchr.c: New files.
+       * fopencookie.c: File removed.
+
 2003-08-15  Marcus Brinkmann  <marcus@g10code.de>
 
        * gpgme-config.in: Put gpg-error related flags after gpgme's.
diff --git a/gpgme/funopen.c b/gpgme/funopen.c
new file mode 100644 (file)
index 0000000..e768b05
--- /dev/null
@@ -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
index ed1d25b..6c6c97e 100644 (file)
@@ -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"
 
 \f
 /* Some opaque data types used by GPGME.  */
diff --git a/gpgme/isascii.c b/gpgme/isascii.c
new file mode 100644 (file)
index 0000000..565c716
--- /dev/null
@@ -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 (file)
index 0000000..3e60c55
--- /dev/null
@@ -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;
+}
similarity index 79%
rename from gpgme/fopencookie.c
rename to gpgme/putc_unlocked.c
index 7862b9a..02c6461 100644 (file)
@@ -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.
 #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);
 }
-
-