More work on the dirmngr. It now builds for W32 and W32CE and quick
authorWerner Koch <wk@gnupg.org>
Fri, 6 Aug 2010 13:52:01 +0000 (13:52 +0000)
committerWerner Koch <wk@gnupg.org>
Fri, 6 Aug 2010 13:52:01 +0000 (13:52 +0000)
tests show that it works on W32.

14 files changed:
ChangeLog
common/ChangeLog
common/homedir.c
common/http.c
common/http.h
dirmngr/ChangeLog
dirmngr/certcache.c
dirmngr/crlcache.c
dirmngr/crlfetch.c
dirmngr/dirmngr.c
dirmngr/ldap-wrapper-ce.c
dirmngr/misc.c
dirmngr/misc.h
dirmngr/server.c

index 4755b9d..433b50d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2010-08-05  Werner Koch  <wk@g10code.com>
+
+       * configure.ac (AH_BOTTOM): Remove HTTP_USE_ESTREAM.
+
 2010-08-02  Werner Koch  <wk@g10code.com>
 
        * configure.ac: Require libksba 1.1.0 due to the use of
 2010-08-02  Werner Koch  <wk@g10code.com>
 
        * configure.ac: Require libksba 1.1.0 due to the use of
index 2096ffd..d690534 100644 (file)
@@ -1,3 +1,17 @@
+2010-08-06  Werner Koch  <wk@g10code.com>
+
+       * homedir.c (dirmngr_socket_name) [W32CE]: Base on default homedir.
+       (gnupg_cachedir) [W32CE]: Drop drive letter.
+
+       * http.c (http_open_document): Rename to _http_open_document and
+       add arg ERRSOURCE.  Pass ERRSOURCE to all called funcs.
+       (http_wait_response, http_open, http_parse_uri): Likewise.
+       (do_parse_uri, parse_response, store_header): Change to return an
+       gpg_err_code_t.  Change callers.
+       (send_request): Add arg ERRSOURCE.  Change callers.
+       * http.h (http_open_document, http_wait_response, http_open)
+       (http_parse_uri): Define as macro.
+
 2010-08-05  Werner Koch  <wk@g10code.com>
 
        * estream.h (es_asprintf, es_vasprintf): Add lost prototyps.
 2010-08-05  Werner Koch  <wk@g10code.com>
 
        * estream.h (es_asprintf, es_vasprintf): Add lost prototyps.
index 3cd8e9d..b1bde09 100644 (file)
@@ -412,7 +412,12 @@ gnupg_cachedir (void)
           dir = tmp;
         }
       else
           dir = tmp;
         }
       else
-        dir = "c:\\temp\\cache\\dirmngr";
+        {
+          dir = "c:\\temp\\cache\\gnupg";
+#ifdef HAVE_W32CE_SYSTEM
+          dir += 2;
+#endif
+        }
     }
   return dir;
 #else /*!HAVE_W32_SYSTEM*/
     }
   return dir;
 #else /*!HAVE_W32_SYSTEM*/
@@ -430,6 +435,12 @@ dirmngr_socket_name (void)
 
   if (!name)
     {
 
   if (!name)
     {
+      char *p;
+# ifdef HAVE_W32CE_SYSTEM
+      const char *s1, *s2;
+
+      s1 = default_homedir ();
+# else
       char s1[MAX_PATH];
       const char *s2;
 
       char s1[MAX_PATH];
       const char *s2;
 
@@ -440,9 +451,13 @@ dirmngr_socket_name (void)
         that. */
       if (w32_shgetfolderpath (NULL, CSIDL_WINDOWS, NULL, 0, s1) < 0)
        strcpy (s1, "C:\\WINDOWS");
         that. */
       if (w32_shgetfolderpath (NULL, CSIDL_WINDOWS, NULL, 0, s1) < 0)
        strcpy (s1, "C:\\WINDOWS");
+# endif
       s2 = DIRSEP_S "S.dirmngr";
       name = xmalloc (strlen (s1) + strlen (s2) + 1);
       strcpy (stpcpy (name, s1), s2);
       s2 = DIRSEP_S "S.dirmngr";
       name = xmalloc (strlen (s1) + strlen (s2) + 1);
       strcpy (stpcpy (name, s1), s2);
+      for (p=name; *p; p++)
+        if (*p == '/')
+          *p = '\\';
     }
   return name;
 #else /*!HAVE_W32_SYSTEM*/
     }
   return name;
 #else /*!HAVE_W32_SYSTEM*/
index 4ce7420..1e3e897 100644 (file)
@@ -131,21 +131,18 @@ typedef unsigned long longcounter_t;
 # define counter_strtoul(a) strtoul ((a), NULL, 10)
 #endif
 
 # define counter_strtoul(a) strtoul ((a), NULL, 10)
 #endif
 
-#if defined(HTTP_USE_ESTREAM) && defined (__GNUC__)
-# warning HTTP_USE_ESTREAM is an obsolete macro
-#endif
-
 #ifndef HTTP_USE_GNUTLS
 typedef void * gnutls_session_t;
 #endif
 
 #ifndef HTTP_USE_GNUTLS
 typedef void * gnutls_session_t;
 #endif
 
-static gpg_error_t do_parse_uri (parsed_uri_t uri, int only_local_part);
+static gpg_err_code_t do_parse_uri (parsed_uri_t uri, int only_local_part);
 static int remove_escapes (char *string);
 static int insert_escapes (char *buffer, const char *string,
                            const char *special);
 static uri_tuple_t parse_tuple (char *string);
 static gpg_error_t send_request (http_t hd, const char *auth,const char *proxy,
 static int remove_escapes (char *string);
 static int insert_escapes (char *buffer, const char *string,
                            const char *special);
 static uri_tuple_t parse_tuple (char *string);
 static gpg_error_t send_request (http_t hd, const char *auth,const char *proxy,
-                                const char *srvtag,strlist_t headers);
+                                const char *srvtag,strlist_t headers,
+                                 gpg_err_source_t errsource);
 static char *build_rel_path (parsed_uri_t uri);
 static gpg_error_t parse_response (http_t hd);
 
 static char *build_rel_path (parsed_uri_t uri);
 static gpg_error_t parse_response (http_t hd);
 
@@ -334,9 +331,10 @@ http_register_tls_callback ( gpg_error_t (*cb) (http_t, void *, int) )
    pointer for completing the the request and to wait for the
    response. */
 gpg_error_t
    pointer for completing the the request and to wait for the
    response. */
 gpg_error_t
-http_open (http_t *r_hd, http_req_t reqtype, const char *url, 
-           const char *auth, unsigned int flags, const char *proxy,
-           void *tls_context, const char *srvtag,strlist_t headers)
+_http_open (http_t *r_hd, http_req_t reqtype, const char *url, 
+            const char *auth, unsigned int flags, const char *proxy,
+            void *tls_context, const char *srvtag, strlist_t headers,
+            gpg_err_source_t errsource)
 {
   gpg_error_t err;
   http_t hd;
 {
   gpg_error_t err;
   http_t hd;
@@ -344,7 +342,7 @@ http_open (http_t *r_hd, http_req_t reqtype, const char *url,
   *r_hd = NULL;
 
   if (!(reqtype == HTTP_REQ_GET || reqtype == HTTP_REQ_POST))
   *r_hd = NULL;
 
   if (!(reqtype == HTTP_REQ_GET || reqtype == HTTP_REQ_POST))
-    return gpg_error (GPG_ERR_INV_ARG);
+    return gpg_err_make (errsource, GPG_ERR_INV_ARG);
 
   /* Create the handle. */
   hd = xtrycalloc (1, sizeof *hd);
 
   /* Create the handle. */
   hd = xtrycalloc (1, sizeof *hd);
@@ -355,9 +353,9 @@ http_open (http_t *r_hd, http_req_t reqtype, const char *url,
   hd->flags = flags;
   hd->tls_context = tls_context;
 
   hd->flags = flags;
   hd->tls_context = tls_context;
 
-  err = http_parse_uri (&hd->uri, url);
+  err = _http_parse_uri (&hd->uri, url, errsource);
   if (!err)
   if (!err)
-    err = send_request (hd, auth, proxy, srvtag, headers);
+    err = send_request (hd, auth, proxy, srvtag, headers, errsource);
   
   if (err)
     {
   
   if (err)
     {
@@ -391,7 +389,7 @@ http_start_data (http_t hd)
 
 
 gpg_error_t
 
 
 gpg_error_t
-http_wait_response (http_t hd)
+_http_wait_response (http_t hd, gpg_err_source_t errsource)
 {
   gpg_error_t err;
   cookie_t cookie;
 {
   gpg_error_t err;
   cookie_t cookie;
@@ -402,7 +400,7 @@ http_wait_response (http_t hd)
   /* Close the write stream but keep the socket open.  */
   cookie = hd->write_cookie;
   if (!cookie)
   /* Close the write stream but keep the socket open.  */
   cookie = hd->write_cookie;
   if (!cookie)
-    return gpg_error (GPG_ERR_INTERNAL);
+    return gpg_err_make (errsource, GPG_ERR_INTERNAL);
 
   cookie->keep_socket = 1;
   es_fclose (hd->fp_write);
 
   cookie->keep_socket = 1;
   es_fclose (hd->fp_write);
@@ -420,7 +418,7 @@ http_wait_response (http_t hd)
   /* Create a new cookie and a stream for reading.  */
   cookie = xtrycalloc (1, sizeof *cookie);
   if (!cookie)
   /* Create a new cookie and a stream for reading.  */
   cookie = xtrycalloc (1, sizeof *cookie);
   if (!cookie)
-    return gpg_error_from_syserror ();
+    return gpg_err_make (errsource, gpg_err_code_from_syserror ());
   cookie->fd = hd->sock;
   if (hd->uri->use_tls)
     cookie->tls_session = hd->tls_context;
   cookie->fd = hd->sock;
   if (hd->uri->use_tls)
     cookie->tls_session = hd->tls_context;
@@ -431,7 +429,7 @@ http_wait_response (http_t hd)
     {
       xfree (cookie);
       hd->read_cookie = NULL;
     {
       xfree (cookie);
       hd->read_cookie = NULL;
-      return gpg_error_from_syserror ();
+      return gpg_err_make (errsource, gpg_err_code_from_syserror ());
     }
 
   err = parse_response (hd);
     }
 
   err = parse_response (hd);
@@ -444,18 +442,19 @@ http_wait_response (http_t hd)
    be used as an HTTP proxy and any enabled $http_proxy gets
    ignored. */
 gpg_error_t
    be used as an HTTP proxy and any enabled $http_proxy gets
    ignored. */
 gpg_error_t
-http_open_document (http_t *r_hd, const char *document, 
-                    const char *auth, unsigned int flags, const char *proxy,
-                    void *tls_context, const char *srvtag,strlist_t headers)
+_http_open_document (http_t *r_hd, const char *document, 
+                     const char *auth, unsigned int flags, const char *proxy,
+                     void *tls_context, const char *srvtag, strlist_t headers,
+                     gpg_err_source_t errsource)
 {
   gpg_error_t err;
 
 {
   gpg_error_t err;
 
-  err = http_open (r_hd, HTTP_REQ_GET, document, auth, flags,
-                   proxy, tls_context, srvtag, headers);
+  err = _http_open (r_hd, HTTP_REQ_GET, document, auth, flags,
+                    proxy, tls_context, srvtag, headers, errsource);
   if (err)
     return err;
 
   if (err)
     return err;
 
-  err = http_wait_response (*r_hd);
+  err = _http_wait_response (*r_hd, errsource);
   if (err)
     http_close (*r_hd, 0);
 
   if (err)
     http_close (*r_hd, 0);
 
@@ -513,13 +512,14 @@ http_get_status_code (http_t hd)
  * resources (even on error).
  */
 gpg_error_t
  * resources (even on error).
  */
 gpg_error_t
-http_parse_uri (parsed_uri_t * ret_uri, const char *uri)
+_http_parse_uri (parsed_uri_t * ret_uri, const char *uri,
+                 gpg_err_source_t errsource)
 {
   *ret_uri = xtrycalloc (1, sizeof **ret_uri + strlen (uri));
   if (!*ret_uri)
 {
   *ret_uri = xtrycalloc (1, sizeof **ret_uri + strlen (uri));
   if (!*ret_uri)
-    return gpg_error_from_syserror ();
+    return gpg_err_make (errsource, gpg_err_code_from_syserror ());
   strcpy ((*ret_uri)->buffer, uri);
   strcpy ((*ret_uri)->buffer, uri);
-  return do_parse_uri (*ret_uri, 0);
+  return gpg_err_make (errsource, do_parse_uri (*ret_uri, 0));
 }
 
 void
 }
 
 void
@@ -539,7 +539,7 @@ http_release_parsed_uri (parsed_uri_t uri)
 }
 
 
 }
 
 
-static gpg_error_t
+static gpg_err_code_t
 do_parse_uri (parsed_uri_t uri, int only_local_part)
 {
   uri_tuple_t *tail;
 do_parse_uri (parsed_uri_t uri, int only_local_part)
 {
   uri_tuple_t *tail;
@@ -557,13 +557,13 @@ do_parse_uri (parsed_uri_t uri, int only_local_part)
 
   /* A quick validity check. */
   if (strspn (p, VALID_URI_CHARS) != n)
 
   /* A quick validity check. */
   if (strspn (p, VALID_URI_CHARS) != n)
-    return gpg_error (GPG_ERR_BAD_URI);        /* Invalid characters found. */
+    return GPG_ERR_BAD_URI;    /* Invalid characters found. */
 
   if (!only_local_part)
     {
       /* Find the scheme. */
       if (!(p2 = strchr (p, ':')) || p2 == p)
 
   if (!only_local_part)
     {
       /* Find the scheme. */
       if (!(p2 = strchr (p, ':')) || p2 == p)
-       return gpg_error (GPG_ERR_BAD_URI); /* No scheme. */
+       return GPG_ERR_BAD_URI; /* No scheme. */
       *p2++ = 0;
       for (pp=p; *pp; pp++)
        *pp = tolower (*(unsigned char*)pp);
       *p2++ = 0;
       for (pp=p; *pp; pp++)
        *pp = tolower (*(unsigned char*)pp);
@@ -578,13 +578,13 @@ do_parse_uri (parsed_uri_t uri, int only_local_part)
         }
 #endif
       else
         }
 #endif
       else
-       return gpg_error (GPG_ERR_INV_URI); /* Unsupported scheme */
+       return GPG_ERR_INV_URI; /* Unsupported scheme */
 
       p = p2;
 
       /* Find the hostname */
       if (*p != '/')
 
       p = p2;
 
       /* Find the hostname */
       if (*p != '/')
-       return gpg_error (GPG_ERR_INV_URI); /* Does not start with a slash. */
+       return GPG_ERR_INV_URI; /* Does not start with a slash. */
 
       p++;
       if (*p == '/') /* There seems to be a hostname. */
 
       p++;
       if (*p == '/') /* There seems to be a hostname. */
@@ -622,9 +622,9 @@ do_parse_uri (parsed_uri_t uri, int only_local_part)
            }
 
          if ((n = remove_escapes (uri->host)) < 0)
            }
 
          if ((n = remove_escapes (uri->host)) < 0)
-           return gpg_error (GPG_ERR_BAD_URI);
+           return GPG_ERR_BAD_URI;
          if (n != strlen (uri->host))
          if (n != strlen (uri->host))
-           return gpg_error (GPG_ERR_BAD_URI); /* Hostname incudes a Nul. */
+           return GPG_ERR_BAD_URI;     /* Hostname incudes a Nul. */
          p = p2 ? p2 : NULL;
        }
     } /* End global URI part. */
          p = p2 ? p2 : NULL;
        }
     } /* End global URI part. */
@@ -641,9 +641,9 @@ do_parse_uri (parsed_uri_t uri, int only_local_part)
 
   uri->path = p;
   if ((n = remove_escapes (p)) < 0)
 
   uri->path = p;
   if ((n = remove_escapes (p)) < 0)
-    return gpg_error (GPG_ERR_BAD_URI);
+    return GPG_ERR_BAD_URI;
   if (n != strlen (p))
   if (n != strlen (p))
-    return gpg_error (GPG_ERR_BAD_URI);        /* Path includes a Nul. */
+    return GPG_ERR_BAD_URI;    /* Path includes a Nul. */
   p = p2 ? p2 : NULL;
 
   if (!p || !*p)       
   p = p2 ? p2 : NULL;
 
   if (!p || !*p)       
@@ -658,7 +658,7 @@ do_parse_uri (parsed_uri_t uri, int only_local_part)
       if ((p2 = strchr (p, '&')))
        *p2++ = 0;
       if (!(elem = parse_tuple (p)))
       if ((p2 = strchr (p, '&')))
        *p2++ = 0;
       if (!(elem = parse_tuple (p)))
-       return gpg_error (GPG_ERR_BAD_URI);
+       return GPG_ERR_BAD_URI;
       *tail = elem;
       tail = &elem->next;
 
       *tail = elem;
       tail = &elem->next;
 
@@ -816,7 +816,8 @@ parse_tuple (char *string)
  */
 static gpg_error_t
 send_request (http_t hd, const char *auth,
  */
 static gpg_error_t
 send_request (http_t hd, const char *auth,
-             const char *proxy,const char *srvtag,strlist_t headers)
+             const char *proxy, const char *srvtag, strlist_t headers,
+              gpg_err_source_t errsource)
 {
   gnutls_session_t tls_session;
   gpg_error_t err;
 {
   gnutls_session_t tls_session;
   gpg_error_t err;
@@ -832,7 +833,7 @@ send_request (http_t hd, const char *auth,
   if (hd->uri->use_tls && !tls_session)
     {
       log_error ("TLS requested but no GNUTLS context provided\n");
   if (hd->uri->use_tls && !tls_session)
     {
       log_error ("TLS requested but no GNUTLS context provided\n");
-      return gpg_error (GPG_ERR_INTERNAL);
+      return gpg_err_make (errsource, GPG_ERR_INTERNAL);
     }
 
   server = *hd->uri->host ? hd->uri->host : "localhost";
     }
 
   server = *hd->uri->host ? hd->uri->host : "localhost";
@@ -848,14 +849,13 @@ send_request (http_t hd, const char *auth,
       if (proxy)
        http_proxy = proxy;
 
       if (proxy)
        http_proxy = proxy;
 
-      err = http_parse_uri (&uri, http_proxy);
+      err = _http_parse_uri (&uri, http_proxy, errsource);
       if (err)
        {
          log_error ("invalid HTTP proxy (%s): %s\n",
                     http_proxy, gpg_strerror (err));
          http_release_parsed_uri (uri);
       if (err)
        {
          log_error ("invalid HTTP proxy (%s): %s\n",
                     http_proxy, gpg_strerror (err));
          http_release_parsed_uri (uri);
-         return gpg_error (GPG_ERR_CONFIGURATION);
-
+         return gpg_err_make (errsource, GPG_ERR_CONFIGURATION);
        }
 
       if (uri->auth)
        }
 
       if (uri->auth)
@@ -866,7 +866,7 @@ send_request (http_t hd, const char *auth,
                                             uri->auth, strlen(uri->auth));
           if (!proxy_authstr)
             {
                                             uri->auth, strlen(uri->auth));
           if (!proxy_authstr)
             {
-              err = gpg_error_from_syserror ();
+              err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
               http_release_parsed_uri (uri);
               return err;
             }
               http_release_parsed_uri (uri);
               return err;
             }
@@ -887,9 +887,9 @@ send_request (http_t hd, const char *auth,
   if (hd->sock == -1)
     {
       xfree (proxy_authstr);
   if (hd->sock == -1)
     {
       xfree (proxy_authstr);
-      return (save_errno 
-              ? gpg_error_from_errno (save_errno)
-              : gpg_error (GPG_ERR_NOT_FOUND));
+      return gpg_err_make (errsource, (save_errno 
+                                       ? gpg_err_code_from_errno (save_errno)
+                                       : GPG_ERR_NOT_FOUND));
     }
 
 #ifdef HTTP_USE_GNUTLS
     }
 
 #ifdef HTTP_USE_GNUTLS
@@ -907,7 +907,7 @@ send_request (http_t hd, const char *auth,
         {
           log_info ("TLS handshake failed: %s\n", gnutls_strerror (rc));
           xfree (proxy_authstr);
         {
           log_info ("TLS handshake failed: %s\n", gnutls_strerror (rc));
           xfree (proxy_authstr);
-          return gpg_error (GPG_ERR_NETWORK);
+          return gpg_err_make (errsource, GPG_ERR_NETWORK);
         }
 
       if (tls_callback)
         }
 
       if (tls_callback)
@@ -934,7 +934,7 @@ send_request (http_t hd, const char *auth,
           if (!myauth)
             {
               xfree (proxy_authstr);
           if (!myauth)
             {
               xfree (proxy_authstr);
-              return gpg_error_from_syserror ();
+              return gpg_err_make (errsource, gpg_err_code_from_syserror ());
             }
           remove_escapes (myauth);
         }
             }
           remove_escapes (myauth);
         }
@@ -952,13 +952,13 @@ send_request (http_t hd, const char *auth,
       if (!authstr)
         {
           xfree (proxy_authstr);
       if (!authstr)
         {
           xfree (proxy_authstr);
-          return gpg_error_from_syserror ();
+          return gpg_err_make (errsource, gpg_err_code_from_syserror ());
         }
     }
   
   p = build_rel_path (hd->uri);
   if (!p)
         }
     }
   
   p = build_rel_path (hd->uri);
   if (!p)
-    return gpg_error_from_syserror ();
+    return gpg_err_make (errsource, gpg_err_code_from_syserror ());
 
   if (http_proxy && *http_proxy)
     {
 
   if (http_proxy && *http_proxy)
     {
@@ -991,7 +991,7 @@ send_request (http_t hd, const char *auth,
   xfree (p);
   if (!request)
     {
   xfree (p);
   if (!request)
     {
-      err = gpg_error_from_syserror ();
+      err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
       xfree (authstr);
       xfree (proxy_authstr);
       return err;
       xfree (authstr);
       xfree (proxy_authstr);
       return err;
@@ -1006,7 +1006,7 @@ send_request (http_t hd, const char *auth,
     cookie = xtrycalloc (1, sizeof *cookie);
     if (!cookie)
       {
     cookie = xtrycalloc (1, sizeof *cookie);
     if (!cookie)
       {
-        err = gpg_error_from_syserror ();
+        err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
         goto leave;
       }
     cookie->fd = hd->sock;
         goto leave;
       }
     cookie->fd = hd->sock;
@@ -1017,12 +1017,12 @@ send_request (http_t hd, const char *auth,
     hd->fp_write = es_fopencookie (cookie, "w", cookie_functions);
     if (!hd->fp_write)
       {
     hd->fp_write = es_fopencookie (cookie, "w", cookie_functions);
     if (!hd->fp_write)
       {
+        err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
         xfree (cookie);
         hd->write_cookie = NULL;
         xfree (cookie);
         hd->write_cookie = NULL;
-        err = gpg_error_from_syserror ();
       }
     else if (es_fputs (request, hd->fp_write) || es_fflush (hd->fp_write))
       }
     else if (es_fputs (request, hd->fp_write) || es_fflush (hd->fp_write))
-      err = gpg_error_from_syserror ();
+      err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
     else
       err = 0;
 
     else
       err = 0;
 
@@ -1033,7 +1033,7 @@ send_request (http_t hd, const char *auth,
           if ((es_fputs (headers->d, hd->fp_write) || es_fflush (hd->fp_write))
               || (es_fputs("\r\n",hd->fp_write) || es_fflush(hd->fp_write)))
             {
           if ((es_fputs (headers->d, hd->fp_write) || es_fflush (hd->fp_write))
               || (es_fputs("\r\n",hd->fp_write) || es_fflush(hd->fp_write)))
             {
-              err = gpg_error_from_syserror ();
+              err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
               break;
             }
         }
               break;
             }
         }
@@ -1128,7 +1128,7 @@ capitalize_header_name (char *name)
 /* Store an HTTP header line in LINE away.  Line continuation is
    supported as well as merging of headers with the same name. This
    function may modify LINE. */
 /* Store an HTTP header line in LINE away.  Line continuation is
    supported as well as merging of headers with the same name. This
    function may modify LINE. */
-static gpg_error_t
+static gpg_err_code_t
 store_header (http_t hd, char *line)
 {
   size_t n;
 store_header (http_t hd, char *line)
 {
   size_t n;
@@ -1143,17 +1143,17 @@ store_header (http_t hd, char *line)
         line[--n] = 0;
     }
   if (!n)  /* we are never called to hit this. */
         line[--n] = 0;
     }
   if (!n)  /* we are never called to hit this. */
-    return gpg_error (GPG_ERR_BUG);
+    return GPG_ERR_BUG;
   if (*line == ' ' || *line == '\t')
     {
       /* Continuation. This won't happen too often as it is not
          recommended.  We use a straightforward implementaion. */
       if (!hd->headers)
   if (*line == ' ' || *line == '\t')
     {
       /* Continuation. This won't happen too often as it is not
          recommended.  We use a straightforward implementaion. */
       if (!hd->headers)
-        return gpg_error (GPG_ERR_PROTOCOL_VIOLATION);
+        return GPG_ERR_PROTOCOL_VIOLATION;
       n += strlen (hd->headers->value);
       p = xtrymalloc (n+1);
       if (!p)
       n += strlen (hd->headers->value);
       p = xtrymalloc (n+1);
       if (!p)
-        return gpg_error_from_syserror ();
+        return gpg_err_code_from_syserror ();
       strcpy (stpcpy (p, hd->headers->value), line);
       xfree (hd->headers->value);
       hd->headers->value = p;
       strcpy (stpcpy (p, hd->headers->value), line);
       xfree (hd->headers->value);
       hd->headers->value = p;
@@ -1163,7 +1163,7 @@ store_header (http_t hd, char *line)
   capitalize_header_name (line);
   p = strchr (line, ':');
   if (!p)
   capitalize_header_name (line);
   p = strchr (line, ':');
   if (!p)
-    return gpg_error (GPG_ERR_PROTOCOL_VIOLATION);
+    return GPG_ERR_PROTOCOL_VIOLATION;
   *p++ = 0;
   while (*p == ' ' || *p == '\t')
     p++;
   *p++ = 0;
   while (*p == ' ' || *p == '\t')
     p++;
@@ -1178,7 +1178,7 @@ store_header (http_t hd, char *line)
          it is a comma separated list and merge them.  */
       p = xtrymalloc (strlen (h->value) + 1 + strlen (value)+ 1);
       if (!p)
          it is a comma separated list and merge them.  */
       p = xtrymalloc (strlen (h->value) + 1 + strlen (value)+ 1);
       if (!p)
-        return gpg_error_from_syserror ();
+        return gpg_err_code_from_syserror ();
       strcpy (stpcpy (stpcpy (p, h->value), ","), value);
       xfree (h->value);
       h->value = p;
       strcpy (stpcpy (stpcpy (p, h->value), ","), value);
       xfree (h->value);
       h->value = p;
@@ -1188,13 +1188,13 @@ store_header (http_t hd, char *line)
   /* Append a new header. */
   h = xtrymalloc (sizeof *h + strlen (line));
   if (!h)
   /* Append a new header. */
   h = xtrymalloc (sizeof *h + strlen (line));
   if (!h)
-    return gpg_error_from_syserror ();
+    return gpg_err_code_from_syserror ();
   strcpy (h->name, line);
   h->value = xtrymalloc (strlen (value)+1);
   if (!h->value)
     {
       xfree (h);
   strcpy (h->name, line);
   h->value = xtrymalloc (strlen (value)+1);
   if (!h->value)
     {
       xfree (h);
-      return gpg_error_from_syserror ();
+      return gpg_err_code_from_syserror ();
     }
   strcpy (h->value, value);
   h->next = hd->headers;
     }
   strcpy (h->value, value);
   h->next = hd->headers;
@@ -1226,7 +1226,7 @@ http_get_header (http_t hd, const char *name)
  * Parse the response from a server.
  * Returns: Errorcode and sets some files in the handle
  */
  * Parse the response from a server.
  * Returns: Errorcode and sets some files in the handle
  */
-static gpg_error_t
+static gpg_err_code_t
 parse_response (http_t hd)
 {
   char *line, *p, *p2;
 parse_response (http_t hd)
 {
   char *line, *p, *p2;
@@ -1250,12 +1250,13 @@ parse_response (http_t hd)
       len = es_read_line (hd->fp_read, &hd->buffer, &hd->buffer_size, &maxlen);
       line = hd->buffer;
       if (!line)
       len = es_read_line (hd->fp_read, &hd->buffer, &hd->buffer_size, &maxlen);
       line = hd->buffer;
       if (!line)
-       return gpg_error_from_syserror (); /* Out of core. */
+       return gpg_err_code_from_syserror (); /* Out of core. */
       if (!maxlen)
       if (!maxlen)
-       return gpg_error (GPG_ERR_TRUNCATED); /* Line has been truncated. */
+       return GPG_ERR_TRUNCATED; /* Line has been truncated. */
       if (!len)
       if (!len)
-       return gpg_error (GPG_ERR_EOF);
-      if ( (hd->flags & HTTP_FLAG_LOG_RESP) )
+       return GPG_ERR_EOF;
+
+      if ((hd->flags & HTTP_FLAG_LOG_RESP))
         log_info ("RESP: `%.*s'\n",
                   (int)strlen(line)-(*line&&line[1]?2:0),line);
     }
         log_info ("RESP: `%.*s'\n",
                   (int)strlen(line)-(*line&&line[1]?2:0),line);
     }
@@ -1294,21 +1295,21 @@ parse_response (http_t hd)
       len = es_read_line (hd->fp_read, &hd->buffer, &hd->buffer_size, &maxlen);
       line = hd->buffer;
       if (!line)
       len = es_read_line (hd->fp_read, &hd->buffer, &hd->buffer_size, &maxlen);
       line = hd->buffer;
       if (!line)
-       return gpg_error_from_syserror (); /* Out of core. */
+       return gpg_err_code_from_syserror (); /* Out of core. */
       /* Note, that we can silently ignore truncated lines. */
       if (!len)
       /* Note, that we can silently ignore truncated lines. */
       if (!len)
-       return gpg_error (GPG_ERR_EOF);
+       return GPG_ERR_EOF;
       /* Trim line endings of empty lines. */
       if ((*line == '\r' && line[1] == '\n') || *line == '\n')
        *line = 0;
       /* Trim line endings of empty lines. */
       if ((*line == '\r' && line[1] == '\n') || *line == '\n')
        *line = 0;
-      if ( (hd->flags & HTTP_FLAG_LOG_RESP) )
+      if ((hd->flags & HTTP_FLAG_LOG_RESP))
         log_info ("RESP: `%.*s'\n",
                   (int)strlen(line)-(*line&&line[1]?2:0),line);
       if (*line)
         {
         log_info ("RESP: `%.*s'\n",
                   (int)strlen(line)-(*line&&line[1]?2:0),line);
       if (*line)
         {
-          gpg_error_t err = store_header (hd, line);
-          if (err)
-            return err;
+          gpg_err_code_t ec = store_header (hd, line);
+          if (ec)
+            return ec;
         }
     }
   while (len && *line);
         }
     }
   while (len && *line);
index 2dd612e..ac9cb15 100644 (file)
@@ -70,33 +70,44 @@ typedef struct http_context_s *http_t;
 
 void http_register_tls_callback (gpg_error_t (*cb) (http_t, void *, int));
 
 
 void http_register_tls_callback (gpg_error_t (*cb) (http_t, void *, int));
 
-gpg_error_t http_parse_uri (parsed_uri_t *ret_uri, const char *uri);
+gpg_error_t _http_parse_uri (parsed_uri_t *ret_uri, const char *uri,
+                             gpg_err_source_t errsource);
+#define http_parse_uri(a,b) \
+  _http_parse_uri ((a), (b), GPG_ERR_SOURCE_DEFAULT)
 
 void http_release_parsed_uri (parsed_uri_t uri);
 
 
 void http_release_parsed_uri (parsed_uri_t uri);
 
-gpg_error_t http_open (http_t *r_hd, http_req_t reqtype,
-                       const char *url,
-                       const char *auth,
-                       unsigned int flags,
-                       const char *proxy,
-                       void *tls_context,
-                      const char *srvtag,
-                      strlist_t headers);
+gpg_error_t _http_open (http_t *r_hd, http_req_t reqtype,
+                        const char *url,
+                        const char *auth,
+                        unsigned int flags,
+                        const char *proxy,
+                        void *tls_context,
+                        const char *srvtag,
+                        strlist_t headers,
+                        gpg_err_source_t errsource);
+#define http_open(a,b,c,d,e,f,g,h,i) \
+  _http_open ((a),(b),(c),(d),(e),(f),(g),(h),(i), GPG_ERR_SOURCE_DEFAULT)
 
 void http_start_data (http_t hd);
 
 
 void http_start_data (http_t hd);
 
-gpg_error_t http_wait_response (http_t hd);
+gpg_error_t _http_wait_response (http_t hd, gpg_err_source_t errsource);
+#define http_wait_response(a) \
+  _http_wait_response ((a), GPG_ERR_SOURCE_DEFAULT)
 
 void http_close (http_t hd, int keep_read_stream);
 
 
 void http_close (http_t hd, int keep_read_stream);
 
-gpg_error_t http_open_document (http_t *r_hd,
-                                const char *document,
-                                const char *auth,
-                                unsigned int flags,
-                                const char *proxy,
-                                void *tls_context,
-                               const char *srvtag,
-                               strlist_t headers);
+gpg_error_t _http_open_document (http_t *r_hd,
+                                 const char *document,
+                                 const char *auth,
+                                 unsigned int flags,
+                                 const char *proxy,
+                                 void *tls_context,
+                                 const char *srvtag,
+                                 strlist_t headers,
+                                 gpg_err_source_t errsource);
+#define http_open_document(a,b,c,d,e,f,g,h) \
+  _http_open_document ((a),(b),(c),(d),(e),(f),(g),(h), GPG_ERR_SOURCE_DEFAULT)
 
 estream_t http_get_read_ptr (http_t hd);
 estream_t http_get_write_ptr (http_t hd);
 
 estream_t http_get_read_ptr (http_t hd);
 estream_t http_get_write_ptr (http_t hd);
index 57cc1c7..737ff35 100644 (file)
@@ -1,3 +1,24 @@
+2010-08-06  Werner Koch  <wk@g10code.com>
+
+       * dirmngr.c (JNLIB_NEED_AFLOCAL): Define macro.
+       (main): Use SUN_LEN macro.
+       (main) [W32]: Allow EEXIST in addition to EADDRINUSE.
+       (JNLIB_NEED_AFLOCAL): 
+
+2010-08-05  Werner Koch  <wk@g10code.com>
+
+       * server.c (set_error, leave_cmd): New.
+       (cmd_validate, cmd_ldapserver, cmd_isvalid, cmd_checkcrl)
+       (cmd_checkocsp, cmd_lookup, cmd_listcrls, cmd_cachecert): Use
+       leave_cmd.
+       (cmd_getinfo): New.
+       (data_line_cookie_write, data_line_cookie_close): New.
+       (cmd_listcrls): Replace assuan_get_data_fp by es_fopencookie.
+
+       * misc.c (create_estream_ksba_reader, my_estream_ksba_reader_cb): New.
+       * certcache.c (load_certs_from_dir): Use create_estream_ksba_reader.
+       * crlcache.c (crl_cache_load): Ditto.
+
 2010-08-03  Werner Koch  <wk@g10code.com>
 
        * dirmngr_ldap.c (pth_enter, pth_leave) [USE_LDAPWRAPPER]: Turn
 2010-08-03  Werner Koch  <wk@g10code.com>
 
        * dirmngr_ldap.c (pth_enter, pth_leave) [USE_LDAPWRAPPER]: Turn
index 46d2ac3..d852811 100644 (file)
@@ -360,13 +360,10 @@ load_certs_from_dir (const char *dirname, int are_trusted)
                      fname, strerror (errno));
           continue;
         }
                      fname, strerror (errno));
           continue;
         }
-      err = ksba_reader_new (&reader);
-      if (!err)
-        err = ksba_reader_set_file (reader, fp);
+
+      err = create_estream_ksba_reader (&reader, fp);
       if (err)
         {
       if (err)
         {
-          log_error (_("can't setup KSBA reader: %s\n"), gpg_strerror (err));
-          ksba_reader_release (reader);
           es_fclose (fp);
           continue;
         }
           es_fclose (fp);
           continue;
         }
index 441ae9e..e087419 100644 (file)
@@ -2369,18 +2369,12 @@ crl_cache_load (ctrl_t ctrl, const char *filename)
       return err;
     }
 
       return err;
     }
 
-  err = ksba_reader_new (&reader);
+  err = create_estream_ksba_reader (&reader, fp);
   if (!err)
   if (!err)
-    err = ksba_reader_set_file (reader, fp);
-  if (err)
     {
     {
-      log_error (_("error initializing reader object: %s\n"),
-                 gpg_strerror (err));
+      err = crl_cache_insert (ctrl, filename, reader);
       ksba_reader_release (reader);
       ksba_reader_release (reader);
-      return err;
     }
     }
-  err = crl_cache_insert (ctrl, filename, reader);
-  ksba_reader_release (reader);
   es_fclose (fp);
   return err;
 }
   es_fclose (fp);
   return err;
 }
index 6c2762c..83897a6 100644 (file)
@@ -30,6 +30,7 @@
 #include "http.h"
 
 #include "estream.h"
 #include "http.h"
 
 #include "estream.h"
+#include "ldap-wrapper.h"
 
 
 /* For detecting armored CRLs received via HTTP (yes, such CRLS really
 
 
 /* For detecting armored CRLs received via HTTP (yes, such CRLS really
@@ -228,7 +229,8 @@ crl_fetch (ctrl_t ctrl, const char *url, ksba_reader_t *reader)
                    pointer (or well the callback context) with the
                    reader.  It is only required when closing the
                    reader thus there is no performance issue doing it
                    pointer (or well the callback context) with the
                    reader.  It is only required when closing the
                    reader thus there is no performance issue doing it
-                   this way.  */
+                   this way.  FIXME: We now have a close notification
+                   which might be used here. */
                 register_file_reader (*reader, cb_ctx);
                 http_close (hd, 1);
               }
                 register_file_reader (*reader, cb_ctx);
                 http_close (hd, 1);
               }
index 52efb9b..7aafc48 100644 (file)
@@ -44,6 +44,7 @@
 
 
 #define JNLIB_NEED_LOG_LOGV
 
 
 #define JNLIB_NEED_LOG_LOGV
+#define JNLIB_NEED_AFLOCAL
 #include "dirmngr.h"
 
 #include <assuan.h> 
 #include "dirmngr.h"
 
 #include <assuan.h> 
@@ -963,12 +964,17 @@ main (int argc, char **argv)
       memset (&serv_addr, 0, sizeof serv_addr);
       serv_addr.sun_family = AF_UNIX;
       strcpy (serv_addr.sun_path, socket_name);
       memset (&serv_addr, 0, sizeof serv_addr);
       serv_addr.sun_family = AF_UNIX;
       strcpy (serv_addr.sun_path, socket_name);
-      len = (offsetof (struct sockaddr_un, sun_path)
-             + strlen (serv_addr.sun_path) + 1);
+      len = SUN_LEN (&serv_addr);
 
       rc = assuan_sock_bind (fd, (struct sockaddr*) &serv_addr, len);
 
       rc = assuan_sock_bind (fd, (struct sockaddr*) &serv_addr, len);
-      if (rc == -1 && errno == EADDRINUSE)
+      if (rc == -1 
+          && (errno == EADDRINUSE
+#ifdef HAVE_W32_SYSTEM
+              || errno == EEXIST
+#endif
+              ))
        {
        {
+          /* Fixme: We should test whether a dirmngr is already running. */
          gnupg_remove (socket_name);
          rc = assuan_sock_bind (fd, (struct sockaddr*) &serv_addr, len);
        }
          gnupg_remove (socket_name);
          rc = assuan_sock_bind (fd, (struct sockaddr*) &serv_addr, len);
        }
index b551534..9e6f785 100644 (file)
@@ -199,7 +199,7 @@ outstream_reader_cb (void *cb_value, char *buffer, size_t count,
   const char *src;
   size_t nread = 0;
 
   const char *src;
   size_t nread = 0;
 
-  if (!buffer && !count && !nread)
+  if (!buffer && !count && !r_nread)
     return gpg_error (GPG_ERR_NOT_SUPPORTED); /* Rewind is not supported.  */
 
   *r_nread = 0;
     return gpg_error (GPG_ERR_NOT_SUPPORTED); /* Rewind is not supported.  */
 
   *r_nread = 0;
index 040d443..3d33bee 100644 (file)
@@ -1,6 +1,6 @@
 /* misc.c - miscellaneous
  *     Copyright (C) 2002 Klarälvdalens Datakonsult AB
 /* misc.c - miscellaneous
  *     Copyright (C) 2002 Klarälvdalens Datakonsult AB
- *      Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+ *      Copyright (C) 2002, 2003, 2004, 2010 Free Software Foundation, Inc.
  *
  * This file is part of DirMngr.
  *
  *
  * This file is part of DirMngr.
  *
@@ -484,3 +484,48 @@ host_and_port_from_url (const char *url, int *port)
   return buf;
 }
 
   return buf;
 }
 
+
+/* A KSBA reader callback to read from an estream.  */
+static int
+my_estream_ksba_reader_cb (void *cb_value, char *buffer, size_t count,
+                           size_t *r_nread)
+{
+  estream_t fp = cb_value;
+  
+  if (!fp)
+    return gpg_error (GPG_ERR_INV_VALUE);
+
+  if (!buffer && !count && !r_nread)
+    {
+      es_rewind (fp);
+      return 0;
+    }
+
+  *r_nread = es_fread (buffer, 1, count, fp);
+  if (!*r_nread)
+    return -1; /* EOF or error.  */
+  return 0; /* Success.  */
+}
+
+
+/* Create a KSBA reader object and connect it to the estream FP.  */
+gpg_error_t
+create_estream_ksba_reader (ksba_reader_t *r_reader, estream_t fp)
+{
+  gpg_error_t err;
+  ksba_reader_t reader;
+
+  *r_reader = NULL;
+  err = ksba_reader_new (&reader);
+  if (!err)
+    err = ksba_reader_set_cb (reader, my_estream_ksba_reader_cb, fp);
+  if (err)
+    {
+      log_error (_("error initializing reader object: %s\n"),
+                 gpg_strerror (err));
+      ksba_reader_release (reader);
+      return err;
+    }
+  *r_reader = reader;
+  return 0;
+}
index b721549..928bf78 100644 (file)
@@ -73,15 +73,9 @@ void dump_cert (const char *text, ksba_cert_t cert);
    URL.  */
 char *host_and_port_from_url (const char *url, int *port);
 
    URL.  */
 char *host_and_port_from_url (const char *url, int *port);
 
+/* Create a KSBA reader object and connect it to the estream FP.  */
+gpg_error_t create_estream_ksba_reader (ksba_reader_t *r_reader, estream_t fp);
 
 
-#ifdef HAVE_FOPENCOOKIE
-/* We have to implement funopen in terms of glibc's fopencookie. */
-FILE *funopen(void *cookie,
-              int (*readfn)(void *, char *, int),
-              int (*writefn)(void *, const char *, int),
-              fpos_t (*seekfn)(void *, fpos_t, int),
-              int (*closefn)(void *));
-#endif /*HAVE_FOPENCOOKIE*/
 
 
 #endif /* MISC_H */
 
 
 #endif /* MISC_H */
index ce0a5b3..584cae7 100644 (file)
@@ -40,6 +40,7 @@
 #include "certcache.h"
 #include "validate.h"
 #include "misc.h"
 #include "certcache.h"
 #include "validate.h"
 #include "misc.h"
+#include "ldap-wrapper.h"
 
 /* To avoid DoS attacks we limit the size of a certificate to
    something reasonable. */
 
 /* To avoid DoS attacks we limit the size of a certificate to
    something reasonable. */
@@ -47,6 +48,7 @@
 
 #define PARM_ERROR(t) assuan_set_error (ctx, \
                                         gpg_error (GPG_ERR_ASS_PARAMETER), (t))
 
 #define PARM_ERROR(t) assuan_set_error (ctx, \
                                         gpg_error (GPG_ERR_ASS_PARAMETER), (t))
+#define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
 
 
 
 
 
 
@@ -61,6 +63,20 @@ struct server_local_s
 };
 
 
 };
 
 
+/* Cookie definition for assuan data line output.  */
+static ssize_t data_line_cookie_write (void *cookie,
+                                       const void *buffer, size_t size);
+static int data_line_cookie_close (void *cookie);
+static es_cookie_io_functions_t data_line_cookie_functions =
+  {
+    NULL,
+    data_line_cookie_write,
+    NULL,
+    data_line_cookie_close
+  };
+
+
+
 
 \f
 /* Accessor for the local ldapservers variable. */
 
 \f
 /* Accessor for the local ldapservers variable. */
@@ -74,6 +90,55 @@ get_ldapservers_from_ctrl (ctrl_t ctrl)
 }
 
 
 }
 
 
+/* Helper to print a message while leaving a command.  */
+static gpg_error_t
+leave_cmd (assuan_context_t ctx, gpg_error_t err)
+{
+  if (err)
+    {
+      const char *name = assuan_get_command_name (ctx);
+      if (!name)
+        name = "?";
+      if (gpg_err_source (err) == GPG_ERR_SOURCE_DEFAULT)
+        log_error ("command '%s' failed: %s\n", name,
+                   gpg_strerror (err));
+      else
+        log_error ("command '%s' failed: %s <%s>\n", name,
+                   gpg_strerror (err), gpg_strsource (err));
+    }
+  return err;
+}
+
+/* A write handler used by es_fopencookie to write assuan data
+   lines.  */
+static ssize_t
+data_line_cookie_write (void *cookie, const void *buffer, size_t size)
+{
+  assuan_context_t ctx = cookie;
+
+  if (assuan_send_data (ctx, buffer, size))
+    {
+      gpg_err_set_errno (EIO);
+      return -1;
+    }
+
+  return size;
+}
+
+static int
+data_line_cookie_close (void *cookie)
+{
+  assuan_context_t ctx = cookie;
+
+  if (assuan_send_data (ctx, NULL, 0))
+    {
+      gpg_err_set_errno (EIO);
+      return -1;
+    }
+
+  return 0;
+}
+
 
 /* Copy the % and + escaped string S into the buffer D and replace the
    escape sequences.  Note, that it is sufficient to allocate the
 
 /* Copy the % and + escaped string S into the buffer D and replace the
    escape sequences.  Note, that it is sufficient to allocate the
@@ -452,17 +517,17 @@ cmd_ldapserver (assuan_context_t ctx, char *line)
   while (spacep (line))
     line++;
   if (*line == '\0')
   while (spacep (line))
     line++;
   if (*line == '\0')
-    return PARM_ERROR (_("ldapserver missing"));
+    return leave_cmd (ctx, PARM_ERROR (_("ldapserver missing")));
 
   server = ldapserver_parse_one (line, "", 0);
   if (! server)
 
   server = ldapserver_parse_one (line, "", 0);
   if (! server)
-    return gpg_error (GPG_ERR_INV_ARG);
+    return leave_cmd (ctx, gpg_error (GPG_ERR_INV_ARG));
 
   last_next_p = &ctrl->server_local->ldapservers;
   while (*last_next_p)
     last_next_p = &(*last_next_p)->next;
   *last_next_p = server;
 
   last_next_p = &ctrl->server_local->ldapservers;
   while (*last_next_p)
     last_next_p = &(*last_next_p)->next;
   *last_next_p = server;
-  return 0;
+  return leave_cmd (ctx, 0);
 }
 
 
 }
 
 
@@ -522,7 +587,7 @@ cmd_isvalid (assuan_context_t ctx, char *line)
       if (strlen (issuerhash) != 40)
         {
           xfree (issuerhash);
       if (strlen (issuerhash) != 40)
         {
           xfree (issuerhash);
-          return PARM_ERROR (_("serialno missing in cert ID"));
+          return leave_cmd (ctx, PARM_ERROR (_("serialno missing in cert ID")));
         }
       ocsp_mode = 1;
     }
         }
       ocsp_mode = 1;
     }
@@ -574,10 +639,8 @@ cmd_isvalid (assuan_context_t ctx, char *line)
         }
     }
 
         }
     }
 
-  if (err)
-    log_error (_("command %s failed: %s\n"), "ISVALID", gpg_strerror (err));
   xfree (issuerhash);
   xfree (issuerhash);
-  return err;
+  return leave_cmd (ctx, err);
 }
 
 
 }
 
 
@@ -688,10 +751,8 @@ cmd_checkcrl (assuan_context_t ctx, char *line)
     }
 
  leave:
     }
 
  leave:
-  if (err)
-    log_error (_("command %s failed: %s\n"), "CHECKCRL", gpg_strerror (err));
   ksba_cert_release (cert);
   ksba_cert_release (cert);
-  return err;
+  return leave_cmd (ctx, err);
 }
 
 
 }
 
 
@@ -773,10 +834,8 @@ cmd_checkocsp (assuan_context_t ctx, char *line)
     err = ocsp_isvalid (ctrl, cert, NULL, force_default_responder);
 
  leave:
     err = ocsp_isvalid (ctrl, cert, NULL, force_default_responder);
 
  leave:
-  if (err)
-    log_error (_("command %s failed: %s\n"), "CHECKOCSP", gpg_strerror (err));
   ksba_cert_release (cert);
   ksba_cert_release (cert);
-  return err;
+  return leave_cmd (ctx, err);
 }
 
 
 }
 
 
@@ -1066,10 +1125,7 @@ cmd_lookup (assuan_context_t ctx, char *line)
   else
     err = lookup_cert_by_pattern (ctx, line, single, cache_only);
 
   else
     err = lookup_cert_by_pattern (ctx, line, single, cache_only);
 
-  if (err)
-    log_error (_("command %s failed: %s\n"), "LOOKUP", gpg_strerror (err));
-
-  return err;
+  return leave_cmd (ctx, err);
 }
 
 
 }
 
 
@@ -1126,9 +1182,7 @@ cmd_loadcrl (assuan_context_t ctx, char *line)
         }
     }
 
         }
     }
 
-  if (err)
-    log_error (_("command %s failed: %s\n"), "LOADCRL", gpg_strerror (err));
-  return err;
+  return leave_cmd (ctx, err);
 }
 
 
 }
 
 
@@ -1143,17 +1197,19 @@ static gpg_error_t
 cmd_listcrls (assuan_context_t ctx, char *line)
 {
   gpg_error_t err;
 cmd_listcrls (assuan_context_t ctx, char *line)
 {
   gpg_error_t err;
-  estream_t fp = assuan_get_data_fp (ctx);
+  estream_t fp;
 
   (void)line;
 
 
   (void)line;
 
+  fp = es_fopencookie (ctx, "w", data_line_cookie_functions);
   if (!fp)
   if (!fp)
-    return PARM_ERROR (_("no data stream"));
-
-  err = crl_cache_list (fp);
-  if (err)
-    log_error (_("command %s failed: %s\n"), "LISTCRLS", gpg_strerror (err));
-  return err;
+    err = set_error (GPG_ERR_ASS_GENERAL, "error setting up a data stream");
+  else
+    {
+      err = crl_cache_list (fp);
+      es_fclose (fp);
+    }
+  return leave_cmd (ctx, err);
 }
 
 
 }
 
 
@@ -1204,10 +1260,8 @@ cmd_cachecert (assuan_context_t ctx, char *line)
   err = cache_cert (cert);
 
  leave:
   err = cache_cert (cert);
 
  leave:
-  if (err)
-    log_error (_("command %s failed: %s\n"), "CACHECERT", gpg_strerror (err));
   ksba_cert_release (cert);
   ksba_cert_release (cert);
-  return err;
+  return leave_cmd (ctx, err);
 }
 
 
 }
 
 
@@ -1273,14 +1327,57 @@ cmd_validate (assuan_context_t ctx, char *line)
   err = validate_cert_chain (ctrl, cert, NULL, VALIDATE_MODE_CERT, NULL);
 
  leave:
   err = validate_cert_chain (ctrl, cert, NULL, VALIDATE_MODE_CERT, NULL);
 
  leave:
-  if (err)
-    log_error (_("command %s failed: %s\n"), "VALIDATE", gpg_strerror (err));
   ksba_cert_release (cert);
   ksba_cert_release (cert);
-  return err;
+  return leave_cmd (ctx, err);
 }
 
 
 }
 
 
+\f
+static const char hlp_getinfo[] = 
+  "GETINFO <what>\n"
+  "\n"
+  "Multi purpose command to return certain information.  \n"
+  "Supported values of WHAT are:\n"
+  "\n"
+  "version     - Return the version of the program.\n"
+  "pid         - Return the process id of the server.\n"
+  "\n"
+  "socket_name - Return the name of the socket.\n";
+static gpg_error_t
+cmd_getinfo (assuan_context_t ctx, char *line)
+{
+  gpg_error_t err;
+
+  if (!strcmp (line, "version"))
+    {
+      const char *s = VERSION;
+      err = assuan_send_data (ctx, s, strlen (s));
+    }
+  else if (!strcmp (line, "pid"))
+    {
+      char numbuf[50];
+
+      snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ());
+      err = assuan_send_data (ctx, numbuf, strlen (numbuf));
+    }
+  else if (!strcmp (line, "socket_name"))
+    {
+      const char *s = dirmngr_socket_name ();
 
 
+      if (s)
+        err = assuan_send_data (ctx, s, strlen (s));
+      else
+        err = gpg_error (GPG_ERR_NO_DATA);
+    }
+  else
+    err = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
+
+  return leave_cmd (ctx, err);
+}
+
+
+
+\f
 /* Tell the assuan library about our commands. */
 static int
 register_commands (assuan_context_t ctx)
 /* Tell the assuan library about our commands. */
 static int
 register_commands (assuan_context_t ctx)
@@ -1299,8 +1396,7 @@ register_commands (assuan_context_t ctx)
     { "LISTCRLS",   cmd_listcrls,   hlp_listcrls },
     { "CACHECERT",  cmd_cachecert,  hlp_cachecert },
     { "VALIDATE",   cmd_validate,   hlp_validate },
     { "LISTCRLS",   cmd_listcrls,   hlp_listcrls },
     { "CACHECERT",  cmd_cachecert,  hlp_cachecert },
     { "VALIDATE",   cmd_validate,   hlp_validate },
-    { "INPUT",      NULL },
-    { "OUTPUT",     NULL },
+    { "GETINFO",    cmd_getinfo,    hlp_getinfo },
     { NULL, NULL }
   };
   int i, j, rc;
     { NULL, NULL }
   };
   int i, j, rc;