p2v: close the mexp handle if mexp_spawnv fails
[miniexpect.git] / miniexpect.c
index fef03fd..8c1efd9 100644 (file)
@@ -21,6 +21,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
+#include <string.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <poll.h>
@@ -53,6 +54,7 @@ create_handle (void)
   h->pcre_error = 0;
   h->buffer = NULL;
   h->len = h->alloc = 0;
+  h->next_match = -1;
   h->user1 = h->user2 = h->user3 = NULL;
 
   return h;
@@ -64,6 +66,7 @@ clear_buffer (mexp_h *h)
   free (h->buffer);
   h->buffer = NULL;
   h->alloc = h->len = 0;
+  h->next_match = -1;
 }
 
 int
@@ -80,6 +83,8 @@ mexp_close (mexp_h *h)
       return -1;
   }
 
+  free (h);
+
   return status;
 }
 
@@ -116,7 +121,7 @@ mexp_spawnl (const char *file, const char *arg, ...)
 mexp_h *
 mexp_spawnv (const char *file, char **argv)
 {
-  mexp_h *h;
+  mexp_h *h = NULL;
   int fd = -1;
   int err;
   char slave[1024];
@@ -192,6 +197,8 @@ mexp_spawnv (const char *file, char **argv)
     close (fd);
   if (pid > 0)
     waitpid (pid, NULL, 0);
+  if (h != NULL)
+    mexp_close (h);
   errno = err;
   return NULL;
 }
@@ -207,8 +214,19 @@ mexp_expect (mexp_h *h, const mexp_regexp *regexps, int *ovector, int ovecsize)
 
   time (&start_t);
 
-  /* Clear the read buffer. */
-  clear_buffer (h);
+  if (h->next_match == -1) {
+    /* Fully clear the buffer, then read. */
+    clear_buffer (h);
+  } else {
+    /* See the comment in the manual about h->next_match.  We have
+     * some data remaining in the buffer, so begin by matching that.
+     */
+    memmove (&h->buffer[0], &h->buffer[h->next_match], h->len - h->next_match);
+    h->len -= h->next_match;
+    h->buffer[h->len] = '\0';
+    h->next_match = -1;
+    goto try_match;
+  }
 
   for (;;) {
     /* If we've got a timeout then work out how many seconds are left.
@@ -273,6 +291,7 @@ mexp_expect (mexp_h *h, const mexp_regexp *regexps, int *ovector, int ovecsize)
     fprintf (stderr, "DEBUG: buffer content: %s\n", h->buffer);
 #endif
 
+  try_match:
     /* See if there is a full or partial match against any regexp. */
     if (regexps) {
       size_t i;
@@ -291,6 +310,10 @@ mexp_expect (mexp_h *h, const mexp_regexp *regexps, int *ovector, int ovecsize)
 
         if (r >= 0) {
           /* A full match. */
+          if (ovector != NULL && ovecsize >= 1 && ovector[1] >= 0)
+            h->next_match = ovector[1];
+          else
+            h->next_match = -1;
           return regexps[i].r;
         }