doc: Describe filter expressions.
[gnupg.git] / common / simple-pwquery.c
index d1b2980..708b157 100644 (file)
@@ -40,7 +40,7 @@
 #include <locale.h>
 #endif
 
-#define JNLIB_NEED_AFLOCAL
+#define GNUPG_COMMON_NEED_AFLOCAL
 #include "../common/mischelp.h"
 #ifdef HAVE_W32_SYSTEM
 #include "../common/w32-afunix.h"
 #define SIMPLE_PWQUERY_IMPLEMENTATION 1
 #include "simple-pwquery.h"
 
-#if defined(SPWQ_USE_LOGGING) && !defined(HAVE_JNLIB_LOGGING)
-# undef SPWQ_USE_LOGGING
-#endif
-
 #ifndef _
 #define _(a) (a)
 #endif
@@ -344,6 +340,7 @@ agent_open (int *rfd)
   if ( !(p = strchr ( infostr, PATHSEP_C)) || p == infostr
        || (p-infostr)+1 >= sizeof client_addr.sun_path )
     {
+      spwq_free (infostr);
       return SPWQ_NO_AGENT;
     }
   *p++ = 0;
@@ -361,12 +358,14 @@ agent_open (int *rfd)
 #ifdef SPWQ_USE_LOGGING
       log_error ("can't create socket: %s\n", strerror(errno) );
 #endif
+      spwq_free (infostr);
       return SPWQ_SYS_ERROR;
     }
 
   memset (&client_addr, 0, sizeof client_addr);
   client_addr.sun_family = AF_UNIX;
   strcpy (client_addr.sun_path, infostr);
+  spwq_free (infostr);
   len = SUN_LEN (&client_addr);
 
 #ifdef HAVE_W32_SYSTEM
@@ -377,7 +376,8 @@ agent_open (int *rfd)
   if (rc == -1)
     {
 #ifdef SPWQ_USE_LOGGING
-      log_error ( _("can't connect to '%s': %s\n"), infostr, strerror (errno));
+      log_error (_("can't connect to '%s': %s\n"),
+                 client_addr.sun_path, strerror (errno));
 #endif
       close (fd );
       return SPWQ_IO_ERROR;
@@ -622,6 +622,7 @@ simple_query (const char *query)
   int fd = -1;
   int nread;
   char response[500];
+  int have = 0;
   int rc;
 
   rc = agent_open (&fd);
@@ -632,40 +633,78 @@ simple_query (const char *query)
   if (rc)
     goto leave;
 
-  /* get response */
-  nread = readline (fd, response, 499);
-  if (nread < 0)
-    {
-      rc = -nread;
-      goto leave;
-    }
-  if (nread < 3)
+  while (1)
     {
-      rc = SPWQ_PROTOCOL_ERROR;
-      goto leave;
-    }
+      if (! have || ! strchr (response, '\n'))
+        /* get response */
+        {
+          nread = readline (fd, &response[have],
+                            sizeof (response) - 1 /* NUL */ - have);
+          if (nread < 0)
+            {
+              rc = -nread;
+              goto leave;
+            }
+          have += nread;
+          if (have < 3)
+            {
+              rc = SPWQ_PROTOCOL_ERROR;
+              goto leave;
+            }
+          response[have] = 0;
+        }
 
-  if (response[0] == 'O' && response[1] == 'K')
-    /* OK, do nothing.  */;
-  else if ((nread > 7 && !memcmp (response, "ERR 111", 7)
-            && (response[7] == ' ' || response[7] == '\n') )
-           || ((nread > 4 && !memcmp (response, "ERR ", 4)
-                && (strtoul (response+4, NULL, 0) & 0xffff) == 99)) )
-    {
-      /* 111 is the old Assuan code for canceled which might still
-         be in use by old installations. 99 is GPG_ERR_CANCELED as
-         used by modern gpg-agents; 0xffff is used to mask out the
-         error source.  */
+      if (response[0] == 'O' && response[1] == 'K')
+        /* OK, do nothing.  */;
+      else if ((nread > 7 && !memcmp (response, "ERR 111", 7)
+                && (response[7] == ' ' || response[7] == '\n') )
+               || ((nread > 4 && !memcmp (response, "ERR ", 4)
+                    && (strtoul (response+4, NULL, 0) & 0xffff) == 99)) )
+        {
+          /* 111 is the old Assuan code for canceled which might still
+             be in use by old installations. 99 is GPG_ERR_CANCELED as
+             used by modern gpg-agents; 0xffff is used to mask out the
+             error source.  */
 #ifdef SPWQ_USE_LOGGING
-      log_info (_("canceled by user\n") );
+          log_info (_("canceled by user\n") );
 #endif
-    }
-  else
-    {
+        }
+      else if (response[0] == 'S' && response[1] == ' ')
+        {
+          char *nextline;
+          int consumed;
+
+          nextline = strchr (response, '\n');
+          if (! nextline)
+            /* Point to the NUL.  */
+            nextline = &response[have];
+          else
+            /* Move past the \n.  */
+            nextline ++;
+
+          consumed = (size_t) nextline - (size_t) response;
+
+          /* Skip any additional newlines.  */
+          while (consumed < have && response[consumed] == '\n')
+            consumed ++;
+
+          have -= consumed;
+
+          if (have)
+            memmove (response, &response[consumed], have + 1);
+
+          continue;
+        }
+      else
+        {
 #ifdef SPWQ_USE_LOGGING
-      log_error (_("problem with the agent\n"));
+          log_error (_("problem with the agent (unexpected response \"%s\")\n"),
+                     response);
 #endif
-      rc = SPWQ_ERR_RESPONSE;
+          rc = SPWQ_ERR_RESPONSE;
+        }
+
+      break;
     }
 
  leave: