gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r22822 - in Extractor: . src/include src/main


From: gnunet
Subject: [GNUnet-SVN] r22822 - in Extractor: . src/include src/main
Date: Sun, 22 Jul 2012 20:20:40 +0200

Author: grothoff
Date: 2012-07-22 20:20:40 +0200 (Sun, 22 Jul 2012)
New Revision: 22822

Added:
   Extractor/src/main/TODO
   Extractor/src/main/extractor_ipc.c
   Extractor/src/main/extractor_plugin_main.c
   Extractor/src/main/extractor_plugin_main.h
Modified:
   Extractor/configure.ac
   Extractor/src/include/extractor.h
   Extractor/src/main/Makefile.am
   Extractor/src/main/extract.c
   Extractor/src/main/extractor.c
   Extractor/src/main/extractor_datasource.c
   Extractor/src/main/extractor_datasource.h
   Extractor/src/main/extractor_ipc.h
   Extractor/src/main/extractor_ipc_gnu.c
   Extractor/src/main/extractor_ipc_w32.c
   Extractor/src/main/extractor_plugins.c
   Extractor/src/main/extractor_plugins.h
   Extractor/src/main/extractor_plugpath.c
   Extractor/src/main/extractor_plugpath.h
Log:
-misc hacking on train

Modified: Extractor/configure.ac
===================================================================
--- Extractor/configure.ac      2012-07-22 14:39:48 UTC (rev 22821)
+++ Extractor/configure.ac      2012-07-22 18:20:40 UTC (rev 22822)
@@ -42,6 +42,7 @@
      AC_DEFINE_UNQUOTED(LINUX,1,[This is a LINUX system])
      AM_CONDITIONAL(HAVE_GNU_LD, true)    
      AM_CONDITIONAL(SOMEBSD, false)
+     AM_CONDITIONAL(WINDOWS, false)
      XTRA_CPPLIBS=-lstdc++
      LIBEXT=.so
      ;;
@@ -50,6 +51,7 @@
      AC_CHECK_LIB(c_r, pthread_create)
      AM_CONDITIONAL(HAVE_GNU_LD, true)
      AM_CONDITIONAL(SOMEBSD, true)
+     AM_CONDITIONAL(WINDOWS, false)
      XTRA_CPPLIBS=-lstdc++
      LIBEXT=.so
      ;;
@@ -58,6 +60,7 @@
      AC_CHECK_LIB(c_r, pthread_create)
      AM_CONDITIONAL(HAVE_GNU_LD, true)
      AM_CONDITIONAL(SOMEBSD, true)
+     AM_CONDITIONAL(WINDOWS, false)
      XTRA_CPPLIBS=-lstdc++
      LIBEXT=.so
      ;;
@@ -66,6 +69,7 @@
      AC_CHECK_LIB(c_r, pthread_create)
      AM_CONDITIONAL(HAVE_GNU_LD, true)
      AM_CONDITIONAL(SOMEBSD, true)
+     AM_CONDITIONAL(WINDOWS, false)
      XTRA_CPPLIBS=-lstdc++
      LIBEXT=.so
      ;;
@@ -75,6 +79,7 @@
      XTRA_CPPLIBS=-lstdc++
      AM_CONDITIONAL(HAVE_GNU_LD, false)
      AM_CONDITIONAL(SOMEBSD, false)
+     AM_CONDITIONAL(WINDOWS, false)
      CFLAGS="-D_POSIX_PTHREAD_SEMANTICS $CFLAGS"
      LIBEXT=.so
      ;;
@@ -82,6 +87,7 @@
      AC_DEFINE_UNQUOTED(DARWIN,1,[This is a Darwin system])
      AM_CONDITIONAL(HAVE_GNU_LD, false)
      AM_CONDITIONAL(SOMEBSD, false)
+     AM_CONDITIONAL(WINDOWS, false)
      CFLAGS="-fno-common $CFLAGS"
      LIBEXT=.so
      ;;
@@ -90,6 +96,7 @@
      LDFLAGS="$LDFLAGS -no-undefined"
      AM_CONDITIONAL(SOMEBSD, false)
      AM_CONDITIONAL(HAVE_GNU_LD, false)
+     AM_CONDITIONAL(WINDOWS, false)
      LIBEXT=.dll
      ;;
 mingw*)
@@ -148,6 +155,7 @@
                 LIBSOLD=$LIBS
      AM_CONDITIONAL(HAVE_GNU_LD, true)
      AM_CONDITIONAL(SOMEBSD, false)
+     AM_CONDITIONAL(WINDOWS, true)
      LIBEXT=.dll
      ;;
 *)
@@ -156,6 +164,7 @@
      AC_MSG_RESULT(otheros)
      AM_CONDITIONAL(HAVE_GNU_LD, false)
      AM_CONDITIONAL(SOMEBSD, false)
+     AM_CONDITIONAL(WINDOWS, false)
      LIBEXT=.so
      ;;
 esac

Modified: Extractor/src/include/extractor.h
===================================================================
--- Extractor/src/include/extractor.h   2012-07-22 14:39:48 UTC (rev 22821)
+++ Extractor/src/include/extractor.h   2012-07-22 18:20:40 UTC (rev 22822)
@@ -4,7 +4,7 @@
 
      libextractor 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, or (at your
+     by the Free Software Foundation; either version 3, or (at your
      option) any later version.
 
      libextractor is distributed in the hope that it will be useful, but

Modified: Extractor/src/main/Makefile.am
===================================================================
--- Extractor/src/main/Makefile.am      2012-07-22 14:39:48 UTC (rev 22821)
+++ Extractor/src/main/Makefile.am      2012-07-22 18:20:40 UTC (rev 22822)
@@ -41,9 +41,10 @@
 
 libextractor_la_SOURCES = \
   extractor.c \
-  $(EXTRACTOR_IPC) extractor_ipc.h \
+  $(EXTRACTOR_IPC) extractor_ipc.c extractor_ipc.h \
   extractor_plugpath.c extractor_plugpath.h \
   extractor_plugins.c extractor_plugins.h \
+  extractor_plugin_main.c extractor_plugin_main.h \
   extractor_metatypes.c \
   extractor_print.c 
 

Added: Extractor/src/main/TODO
===================================================================
--- Extractor/src/main/TODO                             (rev 0)
+++ Extractor/src/main/TODO     2012-07-22 18:20:40 UTC (rev 22822)
@@ -0,0 +1,5 @@
+* extractor_plugin_main (a lot)
+* extractor_ipc.c (a bit)
+* extractor.c (a lot)
+* extractor_ipc_w32.c (a lot)
+* test, test, test (a lot)

Modified: Extractor/src/main/extract.c
===================================================================
--- Extractor/src/main/extract.c        2012-07-22 14:39:48 UTC (rev 22821)
+++ Extractor/src/main/extract.c        2012-07-22 18:20:40 UTC (rev 22822)
@@ -17,6 +17,11 @@
      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      Boston, MA 02111-1307, USA.
 */
+/**
+ * @file main/extract.c
+ * @brief command-line tool to run GNU libextractor
+ * @author Christian Grothoff
+ */
 #include "platform.h"
 #include "extractor.h"
 #include "getopt.h"

Modified: Extractor/src/main/extractor.c
===================================================================
--- Extractor/src/main/extractor.c      2012-07-22 14:39:48 UTC (rev 22821)
+++ Extractor/src/main/extractor.c      2012-07-22 18:20:40 UTC (rev 22822)
@@ -113,36 +113,7 @@
  */
 #define OPMODE_FILE 3
 
-/**
- * Header used for our IPC replies.  A header
- * with all fields being zero is used to indicate
- * the end of the stream.
- */
-struct IpcHeader
-{
-  /**
-   * Type of the meta data.
-   */
-  enum EXTRACTOR_MetaType meta_type;
 
-  /**
-   * Format of the meta data.
-   */
-  enum EXTRACTOR_MetaFormat meta_format;
-
-  /**
-   * Number of bytes of meta data (value)
-   */
-  size_t data_len;
-  
-  /**
-   * Length of the mime type string describing the meta data value's mime type,
-   * including 0-terminator, 0 for mime type of "NULL".
-   */
-  size_t mime_len;
-};
-
-
 /**
  * Writes 'size' bytes from 'buf' to 'fd', returns only when
  * writing is not possible, or when all 'size' bytes were written
@@ -173,345 +144,12 @@
 }
 
 
-/**
- * Function called by a plugin in a child process.  Transmits
- * the meta data back to the parent process.
- *
- * @param cls closure, "int*" of the FD for transmission
- * @param plugin_name name of the plugin that produced this value;
- *        special values can be used (i.e. '<zlib>' for zlib being
- *        used in the main libextractor library and yielding
- *        meta data).
- * @param type libextractor-type describing the meta data
- * @param format basic format information about data 
- * @param data_mime_type mime-type of data (not of the original file);
- *        can be NULL (if mime-type is not known)
- * @param data actual meta-data found
- * @param data_len number of bytes in data
- * @return 0 to continue extracting, 1 to abort (transmission error)
- */ 
-static int
-transmit_reply (void *cls,
-               const char *plugin_name,
-               enum EXTRACTOR_MetaType type,
-               enum EXTRACTOR_MetaFormat format,
-               const char *data_mime_type,
-               const char *data,
-               size_t data_len)
-{
-  static const unsigned char meta_byte = MESSAGE_META;
-  int *cpipe_out = cls;
-  struct IpcHeader hdr;
-  size_t mime_len;
 
-  if (NULL == data_mime_type)
-    mime_len = 0;
-  else
-    mime_len = strlen (data_mime_type) + 1;
-  if (mime_len > MAX_MIME_LEN)
-    mime_len = MAX_MIME_LEN;
-  hdr.meta_type = type;
-  hdr.meta_format = format;
-  hdr.data_len = data_len;
-  hdr.mime_len = mime_len;
-  if ( (sizeof (meta_byte) != 
-       write_all (*cpipe_out,
-                  &meta_byte, sizeof (meta_byte))) ||
-       (sizeof (hdr) != 
-       write_all (*cpipe_out, 
-                  &hdr, sizeof (hdr))) ||
-       (mime_len !=
-       write_all (*cpipe_out, 
-                  data_mime_type, mime_len)) ||
-       (data_len !=
-       write_all (*cpipe_out, 
-                  data, data_len)) )
-    return 1;
-  return 0;
-}
-
-
 /**
- * Main loop function for plugins.
- * Reads a message from the plugin input pipe and acts on it.
- * Can be called recursively (once) in OPMODE_DECOMPRESS.
- * plugin->waiting_for_update == 1 indicates the recursive call.
- *
- * @param plugin plugin context
- * @return 0, always
- */ 
-static int
-process_requests (struct EXTRACTOR_PluginList *plugin)
-{
-  int in, out;
-  int read_result1, read_result2, read_result3, read_result4;
-  unsigned char code;
-  char *shm_name = NULL;
-  size_t shm_name_len;
-  int extract_reply;
-  struct IpcHeader hdr;
-  int do_break;
-#ifdef WINDOWS
-  HANDLE map;
-  MEMORY_BASIC_INFORMATION mi;
-#endif
-
-  in = plugin->pipe_in;
-  out = plugin->cpipe_out;
-
-  /* The point of recursing into this function is to request
-   * a seek from LE server and wait for a reply. This snipper
-   * requests a seek.
-   */
-  if (plugin->waiting_for_update == 1)
-  {
-    unsigned char seek_byte = MESSAGE_SEEK;
-    if (write (out, &seek_byte, 1) != 1)
-      return -1;
-    if (write (out, &plugin->seek_request, sizeof (int64_t)) != sizeof 
(int64_t))
-      return -1;
-  }
-
-  memset (&hdr, 0, sizeof (hdr));
-  do_break = 0;
-  while (!do_break)
-  {
-    read_result1 = read (in, &code, 1);
-    if (read_result1 <= 0)
-      break;
-    switch (code)
-    {
-    case MESSAGE_INIT_STATE:
-      read_result2 = read (in, &plugin->operation_mode, sizeof (uint8_t));
-      read_result3 = read (in, &plugin->fsize, sizeof (int64_t));
-      read_result4 = read (in, &shm_name_len, sizeof (size_t));
-      if ((read_result2 < sizeof (uint8_t)) ||
-          (read_result3 < sizeof (int64_t)) ||
-          (read_result4 < sizeof (size_t)))
-      {
-        do_break = 1;
-        break;
-      }
-      if (plugin->operation_mode != OPMODE_MEMORY &&
-          plugin->operation_mode != OPMODE_DECOMPRESS &&
-          plugin->operation_mode != OPMODE_FILE)
-      {
-        do_break = 1;
-        break;
-      }
-      if ((plugin->operation_mode == OPMODE_MEMORY ||
-          plugin->operation_mode == OPMODE_DECOMPRESS) &&
-          shm_name_len > MAX_SHM_NAME)
-      {
-        do_break = 1;
-        break;
-      }
-      /* Fsize may be -1 only in decompression mode */
-      if (plugin->operation_mode != OPMODE_DECOMPRESS && plugin->fsize <= 0)
-      {
-        do_break = 1;
-        break;
-      }
-      if (shm_name != NULL)
-        free (shm_name);
-      shm_name = malloc (shm_name_len);
-      if (shm_name == NULL)
-      {
-        do_break = 1;
-        break;
-      }
-      read_result2 = read (in, shm_name, shm_name_len);
-      if (read_result2 < shm_name_len)
-      {
-        do_break = 1;
-        break;
-      }
-      shm_name[shm_name_len - 1] = '\0';
-      do_break = init_state_method (plugin, plugin->operation_mode, 
plugin->fsize, shm_name);
-      /* in OPMODE_MEMORY and OPMODE_FILE we can start extracting right away,
-       * there won't be UPDATED_SHM message, and we don't need it
-       */
-      if (!do_break && (plugin->operation_mode == OPMODE_MEMORY ||
-          plugin->operation_mode == OPMODE_FILE))
-      {
-        extract_reply = plugin->extract_method (plugin, transmit_reply, &out);
-        unsigned char done_byte = MESSAGE_DONE;
-        if (write (out, &done_byte, 1) != 1)
-        {
-          do_break = 1;
-          break;
-        }
-        if ((plugin->specials != NULL) &&
-            (NULL != strstr (plugin->specials, "force-kill")))
-        {
-          /* we're required to die after each file since this
-             plugin only supports a single file at a time */
-#if !WINDOWS
-          fsync (out);
-#else
-          _commit (out);
-#endif
-          _exit (0);
-        }
-      }
-      break;
-    case MESSAGE_DISCARD_STATE:
-      discard_state_method (plugin);
-      break;
-    case MESSAGE_UPDATED_SHM:
-      if (plugin->operation_mode == OPMODE_DECOMPRESS)
-      {
-        read_result2 = read (in, &plugin->fpos, sizeof (int64_t));
-        read_result3 = read (in, &plugin->map_size, sizeof (size_t));
-        read_result4 = read (in, &plugin->fsize, sizeof (int64_t));
-        if ((read_result2 < sizeof (int64_t)) || (read_result3 < sizeof 
(size_t)) ||
-            plugin->fpos < 0 || (plugin->operation_mode != OPMODE_DECOMPRESS 
&& (plugin->fsize <= 0 || plugin->fpos >= plugin->fsize)))
-        {
-          do_break = 1;
-          break;
-        }
-        /* FIXME: also check mapped region size (lseek for *nix, VirtualQuery 
for W32) */
-        /* Re-map the shm */
-#if !WINDOWS
-        if ((-1 == plugin->shm_id) ||
-            (NULL == (plugin->shm_ptr = mmap (NULL, plugin->map_size, 
PROT_READ, MAP_SHARED, plugin->shm_id, 0))) ||
-            (plugin->shm_ptr == (void *) -1))
-        {
-          do_break = 1;
-          break;
-        }
-#else
-        if ((plugin->map_handle == 0) ||
-           (NULL == (plugin->shm_ptr = MapViewOfFile (plugin->map_handle, 
FILE_MAP_READ, 0, 0, 0))))
-        {
-          do_break = 1;
-          break;
-        }
-#endif
-        if (plugin->waiting_for_update == 1)
-        {
-          /* We were only waiting for this one message */
-          do_break = 1;
-          plugin->waiting_for_update = 2;
-          break;
-        }
-        /* Run extractor on mapped region (recursive call doesn't reach this
-         * point and breaks out earlier.
-         */
-        extract_reply = plugin->extract_method (plugin, transmit_reply, &out);
-        /* Unmap the shm */
-#if !WINDOWS
-        if ((plugin->shm_ptr != NULL) &&
-            (plugin->shm_ptr != (void*) -1) )
-          munmap (plugin->shm_ptr, plugin->map_size);
-#else
-        if (plugin->shm_ptr != NULL)
-          UnmapViewOfFile (plugin->shm_ptr);
-#endif
-        plugin->shm_ptr = NULL;
-        if (extract_reply == 1)
-        {
-          /* Tell LE that we're done */
-          unsigned char done_byte = MESSAGE_DONE;
-          if (write (out, &done_byte, 1) != 1)
-          {
-            do_break = 1;
-            break;
-          }
-          if ((plugin->specials != NULL) &&
-              (NULL != strstr (plugin->specials, "force-kill")))
-          {
-            /* we're required to die after each file since this
-               plugin only supports a single file at a time */
-#if !WINDOWS
-            fsync (out);
-#else
-            _commit (out);
-#endif
-            _exit (0);
-          }
-        }
-        else
-        {
-          /* Tell LE that we're not done, and we need to seek */
-          unsigned char seek_byte = MESSAGE_SEEK;
-          if (write (out, &seek_byte, 1) != 1)
-          {
-            do_break = 1;
-            break;
-          }
-          if (write (out, &plugin->seek_request, sizeof (int64_t)) != sizeof 
(int64_t))
-          {
-            do_break = 1;
-            break;
-          }
-        }
-      }
-      else
-      {
-        /* This is mostly to safely skip unrelated messages */
-        int64_t t;
-        size_t t2;
-        read_result2 = read (in, &t, sizeof (int64_t));
-        read_result3 = read (in, &t2, sizeof (size_t));
-        read_result4 = read (in, &t, sizeof (int64_t));
-      }
-      break;
-    }
-  }
-  return 0;
-}
-
-
-/**
- * 'main' function of the child process. Loads the plugin,
- * sets up its in and out pipes, then runs the request serving function.
- *
- * @param plugin extractor plugin to use
- * @param in stream to read from
- * @param out stream to write to
- */
-static void
-plugin_main (struct EXTRACTOR_PluginList *plugin, 
-            int in, int out)
-{
-  if (plugin == NULL)
-  {
-    close (in);
-    close (out);
-    return;
-  }
-  if (0 != EXTRACTOR_plugin_load_ (plugin))
-  {
-    close (in);
-    close (out);
-#if DEBUG
-    fprintf (stderr, "Plugin `%s' failed to load!\n", plugin->short_libname);
-#endif
-    return;
-  }  
-  if ((plugin->specials != NULL) &&
-      (NULL != strstr (plugin->specials, "close-stderr")))
-    close (2);
-  if ((plugin->specials != NULL) &&
-      (NULL != strstr (plugin->specials, "close-stdout")))
-    close (1);
-
-  plugin->pipe_in = in;
-  /* Compiler will complain, and it's right. This is a kind of hack...*/
-  plugin->cpipe_out = out;
-  process_requests (plugin);
-
-  close (in);
-  close (out);
-}
-
-
-/**
  * Open a file
  */
 static int 
-file_open(const char *filename, int oflag, ...)
+file_open (const char *filename, int oflag, ...)
 {
   int mode;
   const char *fn;
@@ -794,115 +432,9 @@
 }
 
 
-/**
- * Moves current absolute buffer position to @pos in @whence mode.
- * Will move logical position withouth shifting the buffer, if possible.
- * Will not move beyond the end of file.
- *
- * @param plugin plugin context
- * @param pos position to move to
- * @param whence seek mode (SEEK_CUR, SEEK_SET, SEEK_END)
- * @return new absolute position, -1 on error
- */
-static int64_t
-pl_seek (struct EXTRACTOR_PluginList *plugin, int64_t pos, int whence)
-{
-  switch (whence)
-  {
-  case SEEK_CUR:
-    if (plugin->shm_pos + pos < plugin->map_size && plugin->shm_pos + pos >= 0)
-    {
-      plugin->shm_pos += pos;
-      return plugin->fpos + plugin->shm_pos;
-    }
-    if (0 != pl_pick_next_buffer_at (plugin, plugin->fpos + plugin->shm_pos + 
pos, 1))
-      return -1;
-    plugin->shm_pos += pos;
-    return plugin->fpos + plugin->shm_pos;
-    break;
-  case SEEK_SET:
-    if (pos < 0)
-      return -1;
-    if (pos >= plugin->fpos && pos < plugin->fpos + plugin->map_size)
-    {
-      plugin->shm_pos = pos - plugin->fpos;
-      return pos;
-    }
-    if (0 != pl_pick_next_buffer_at (plugin, pos, 1))
-      return -1;
-    if (pos >= plugin->fpos && pos < plugin->fpos + plugin->map_size)
-    {
-      plugin->shm_pos = pos - plugin->fpos;
-      return pos;
-    }
-    return -1;
-    break;
-  case SEEK_END:
-    while (plugin->fsize == -1)
-    {
-      pl_pick_next_buffer_at (plugin, plugin->fpos + plugin->map_size + pos, 
0);
-    }
-    if (plugin->fsize + pos - 1 < plugin->fpos || plugin->fsize + pos - 1 > 
plugin->fpos + plugin->map_size)
-    {
-      if (0 != pl_pick_next_buffer_at (plugin, plugin->fsize - MAX_READ, 0))
-        return -1;
-    }
-    plugin->shm_pos = plugin->fsize + pos - plugin->fpos;
-    if (plugin->shm_pos < 0)
-      plugin->shm_pos = 0;
-    else if (plugin->shm_pos >= plugin->map_size)
-      plugin->shm_pos = plugin->map_size - 1;
-    return plugin->fpos + plugin->shm_pos - 1;
-    break;
-  }
-  return -1;
-}
 
 
-static int64_t
-pl_get_fsize (struct EXTRACTOR_PluginList *plugin)
-{
-  return plugin->fsize;
-}
-
-
 /**
- * Fills @data with a pointer to the data buffer.
- * Equivalent to read(), except you don't have to allocate and free
- * a buffer, since the data is already in memory.
- * Will move the buffer, if necessary
- *
- * @param plugin plugin context
- * @param data location to store data pointer
- * @param count number of bytes to read
- * @return number of bytes (<= count) avalable in @data, -1 on error
- */
-static int64_t
-pl_read (struct EXTRACTOR_PluginList *plugin, unsigned char **data, size_t 
count)
-{
-  *data = NULL;
-  if (count > MAX_READ)
-    return -1;
-  if (count > plugin->map_size - plugin->shm_pos)
-  {
-    int64_t actual_count;
-    if (plugin->fpos + plugin->shm_pos != pl_seek (plugin, plugin->fpos + 
plugin->shm_pos, SEEK_SET))
-      return -1;
-    *data = &plugin->shm_ptr[plugin->shm_pos];
-    actual_count = (count < plugin->map_size - plugin->shm_pos) ? count : 
(plugin->map_size - plugin->shm_pos);
-    plugin->shm_pos += actual_count;
-    return actual_count;
-  }
-  else
-  {
-    *data = &plugin->shm_ptr[plugin->shm_pos];
-    plugin->shm_pos += count;
-    return count;
-  }
-}
-
-
-/**
  * Transmits information about updated shm to plugin.
  * For OPMODE_DECOMPRESS only.
  *
@@ -1002,111 +534,7 @@
 }
 
 
-/**
- * Receive a reply from plugin (seek request, metadata and done message)
- *
- * @param plugin plugin context
- * @param proc metadata callback
- * @param proc_cls callback cls
- * @return 0 on success, -1 on error
- */
-static int
-receive_reply (struct EXTRACTOR_PluginList *plugin,
-              EXTRACTOR_MetaDataProcessor proc, void *proc_cls)
-{
-  int read_result;
-  unsigned char code;
-  int64_t seek_position;
-  struct IpcHeader hdr;
-  char *mime_type;
-  char *data;
-  int must_read = 1;
 
-  while (must_read)
-    {
-      read_result = plugin_read (plugin, &code, 1);
-      if (read_result < 1)
-       return -1;
-      switch (code)
-       {
-       case MESSAGE_DONE: /* Done */
-         plugin->seek_request = -1;
-         must_read = 0;
-         break;
-       case MESSAGE_SEEK: /* Seek */
-         read_result = plugin_read (plugin, 
-                                    &seek_position, sizeof (int64_t));
-         if (read_result < sizeof (int64_t))
-           return -1;
-         plugin->seek_request = seek_position;
-         must_read = 0;
-         break;
-       case MESSAGE_META: /* Meta */
-         read_result = plugin_read (plugin, 
-                                    &hdr, sizeof (hdr));
-         if (read_result < sizeof (hdr)) 
-           return -1;
-         /* FIXME: check hdr for sanity */
-         if (hdr.data_len > MAX_META_DATA)
-           return -1; /* not allowing more than MAX_META_DATA meta data */
-         if (0 == hdr.mime_len)
-           {
-             mime_type = NULL;
-           }
-         else
-           {
-             if (NULL == (mime_type = malloc (hdr.mime_len)))
-               return -1;
-             read_result = plugin_read (plugin, 
-                                        mime_type, 
-                                        hdr.mime_len);
-             if ( (read_result < hdr.mime_len) ||
-                  ('\0' != mime_type[hdr.mime_len-1]) )
-               {
-                 if (NULL != mime_type)
-                   free (mime_type);
-                 return -1;
-               }
-           }
-         if (0 == hdr.data_len)
-           {
-             data = NULL;
-           }
-         else
-           {
-             if (NULL == (data = malloc (hdr.data_len)))
-               {
-                 if (NULL != mime_type)
-                   free (mime_type);
-                 return -1;
-               }
-             read_result = plugin_read (plugin, 
-                                        data, hdr.data_len);
-             if (read_result < hdr.data_len)
-               {
-                 if (NULL != mime_type)
-                   free (mime_type);
-                 free (data);
-                 return -1;
-               }
-           }
-         read_result = proc (proc_cls, 
-                             plugin->short_libname, 
-                             hdr.meta_type, hdr.meta_format,
-                             mime_type, data, hdr.data_len);
-         if (NULL != mime_type)
-           free (mime_type);
-         if (NULL != data)
-           free (data);
-         if (0 != read_result)
-           return 1;
-         break;
-       default:
-         return -1;
-       }
-    }
-  return 0;
-}
 
 
 /**

Modified: Extractor/src/main/extractor_datasource.c
===================================================================
--- Extractor/src/main/extractor_datasource.c   2012-07-22 14:39:48 UTC (rev 
22821)
+++ Extractor/src/main/extractor_datasource.c   2012-07-22 18:20:40 UTC (rev 
22822)
@@ -17,8 +17,14 @@
      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      Boston, MA 02111-1307, USA.
  */
+/**
+ * @file main/extractor_datasource.c
+ * @brief random access and possibly decompression of data from buffer in 
memory or file on disk
+ * @author Christian Grothoff
+ */
 
 #include "platform.h"
+#include "extractor_datasource.h"
 
 #if HAVE_LIBBZ2
 #include <bzlib.h>
@@ -219,13 +225,7 @@
       bfds->buffer_pos = pos;
       return 0;
     }
-#if WINDOWS
-  position = _lseeki64 (bfds->fd, pos, SEEK_SET);
-#elif HAVE_LSEEK64
-  position = lseek64 (bfds->fd, pos, SEEK_SET);
-#else
-  position = (int64_t) lseek (bfds->fd, pos, SEEK_SET);
-#endif
+  position = (int64_t) LSEEK (bfds->fd, pos, SEEK_SET);
   if (position < 0)
     return -1;
   bfds->fpos = position;

Modified: Extractor/src/main/extractor_datasource.h
===================================================================
--- Extractor/src/main/extractor_datasource.h   2012-07-22 14:39:48 UTC (rev 
22821)
+++ Extractor/src/main/extractor_datasource.h   2012-07-22 18:20:40 UTC (rev 
22822)
@@ -17,6 +17,11 @@
      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      Boston, MA 02111-1307, USA.
  */
+/**
+ * @file main/extractor_datasource.h
+ * @brief random access and possibly decompression of data from buffer in 
memory or file on disk
+ * @author Christian Grothoff
+ */
 #ifndef EXTRACTOR_DATASOURCE_H
 #define EXTRACTOR_DATASOURCE_H
 

Added: Extractor/src/main/extractor_ipc.c
===================================================================
--- Extractor/src/main/extractor_ipc.c                          (rev 0)
+++ Extractor/src/main/extractor_ipc.c  2012-07-22 18:20:40 UTC (rev 22822)
@@ -0,0 +1,137 @@
+/*
+     This file is part of libextractor.
+     (C) 2012 Vidyut Samanta and Christian Grothoff
+
+     libextractor 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 3, or (at your
+     option) any later version.
+
+     libextractor 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 libextractor; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+ */
+/**
+ * @file main/extractor_ipc.c
+ * @brief IPC with plugin (OS-independent parts)
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+
+
+/**
+ * Process a reply from channel (seek request, metadata and done message)
+ *
+ * @param buf buffer with data from IPC channel
+ * @param size number of bytes in buffer
+ * @param proc metadata callback
+ * @param proc_cls callback cls
+ * @return number of bytes processed, -1 on error
+ */
+ssize_t
+EXTRACTOR_IPC_process_reply_ (const void *data,
+                             size_t size,
+                             EXTRACTOR_ChannelMessageProcessor proc,
+                             void *proc_cls)
+{
+  int read_result;
+  unsigned char code;
+  int64_t seek_position;
+  struct IpcHeader hdr;
+  char *mime_type;
+  char *data;
+  int must_read = 1;
+
+  while (must_read)
+    {
+      read_result = plugin_read (plugin, &code, 1);
+      if (read_result < 1)
+       return -1;
+      switch (code)
+       {
+       case MESSAGE_DONE: /* Done */
+         plugin->seek_request = -1;
+         must_read = 0;
+         break;
+       case MESSAGE_SEEK: /* Seek */
+         read_result = plugin_read (plugin, 
+                                    &seek_position, sizeof (int64_t));
+         if (read_result < sizeof (int64_t))
+           return -1;
+         plugin->seek_request = seek_position;
+         must_read = 0;
+         break;
+       case MESSAGE_META: /* Meta */
+         read_result = plugin_read (plugin, 
+                                    &hdr, sizeof (hdr));
+         if (read_result < sizeof (hdr)) 
+           return -1;
+         /* FIXME: check hdr for sanity */
+         if (hdr.data_len > MAX_META_DATA)
+           return -1; /* not allowing more than MAX_META_DATA meta data */
+         if (0 == hdr.mime_len)
+           {
+             mime_type = NULL;
+           }
+         else
+           {
+             if (NULL == (mime_type = malloc (hdr.mime_len)))
+               return -1;
+             read_result = plugin_read (plugin, 
+                                        mime_type, 
+                                        hdr.mime_len);
+             if ( (read_result < hdr.mime_len) ||
+                  ('\0' != mime_type[hdr.mime_len-1]) )
+               {
+                 if (NULL != mime_type)
+                   free (mime_type);
+                 return -1;
+               }
+           }
+         if (0 == hdr.data_len)
+           {
+             data = NULL;
+           }
+         else
+           {
+             if (NULL == (data = malloc (hdr.data_len)))
+               {
+                 if (NULL != mime_type)
+                   free (mime_type);
+                 return -1;
+               }
+             read_result = plugin_read (plugin, 
+                                        data, hdr.data_len);
+             if (read_result < hdr.data_len)
+               {
+                 if (NULL != mime_type)
+                   free (mime_type);
+                 free (data);
+                 return -1;
+               }
+           }
+         read_result = proc (proc_cls, 
+                             plugin->short_libname, 
+                             hdr.meta_type, hdr.meta_format,
+                             mime_type, data, hdr.data_len);
+         if (NULL != mime_type)
+           free (mime_type);
+         if (NULL != data)
+           free (data);
+         if (0 != read_result)
+           return 1;
+         break;
+       default:
+         return -1;
+       }
+    }
+  return 0;
+}
+
+/* end of extractor_ipc.c */

Modified: Extractor/src/main/extractor_ipc.h
===================================================================
--- Extractor/src/main/extractor_ipc.h  2012-07-22 14:39:48 UTC (rev 22821)
+++ Extractor/src/main/extractor_ipc.h  2012-07-22 18:20:40 UTC (rev 22822)
@@ -1,6 +1,6 @@
 /*
      This file is part of libextractor.
-     (C) 2002, 2003, 2004, 2005, 2006, 2009, 2012 Vidyut Samanta and Christian 
Grothoff
+     (C) 2012 Vidyut Samanta and Christian Grothoff
 
      libextractor is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
@@ -17,6 +17,11 @@
      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      Boston, MA 02111-1307, USA.
  */
+/**
+ * @file main/extractor_ipc.h
+ * @brief IPC with plugin (OS-independent API)
+ * @author Christian Grothoff
+ */
 #ifndef EXTRACTOR_IPC_H
 #define EXTRACTOR_IPC_H
 
@@ -26,16 +31,89 @@
  */
 struct EXTRACTOR_Channel;
 
+/**
+ * Definition of a shared memory area.
+ */
+struct EXTRACTOR_SharedMemory;
 
+
 /**
+ * Header used for our IPC replies.  A header
+ * with all fields being zero is used to indicate
+ * the end of the stream.
+ */
+struct IpcHeader
+{
+  /**
+   * Type of the meta data.
+   */
+  enum EXTRACTOR_MetaType meta_type;
+
+  /**
+   * Format of the meta data.
+   */
+  enum EXTRACTOR_MetaFormat meta_format;
+
+  /**
+   * Number of bytes of meta data (value)
+   */
+  size_t data_len;
+  
+  /**
+   * Length of the mime type string describing the meta data value's mime type,
+   * including 0-terminator, 0 for mime type of "NULL".
+   */
+  size_t mime_len;
+};
+
+
+/**
+ * Create a shared memory area.
+ *
+ * @param size size of the shared area
+ * @return NULL on error
+ */
+struct EXTRACTOR_SharedMemory *
+EXTRACTOR_IPC_shared_memory_create_ (size_t size);
+
+
+/**
+ * Destroy shared memory area.
+ *
+ * @param shm memory area to destroy
+ * @return NULL on error
+ */
+void
+EXTRACTOR_IPC_shared_memory_destroy_ (struct EXTRACTOR_SharedMemory *shm);
+
+
+/**
+ * Initialize shared memory area from data source.
+ *
+ * @param shm memory area to initialize
+ * @param ds data source to use for initialization
+ * @param off offset to use in data source
+ * @param size number of bytes to copy
+ * @return -1 on error, otherwise number of bytes copied
+ */
+ssize_t
+EXTRACTOR_IPC_shared_memory_set_ (struct EXTRACTOR_SharedMemory *shm,
+                                 struct EXTRACTOR_Datasource *ds,
+                                 uint64_t off,
+                                 size_t size);
+
+
+/**
  * Create a channel to communicate with a process wrapping
  * the plugin of the given name.  Starts the process as well.
  *
  * @param short_libname name of the plugin
+ * @param shm memory to share with the process
  * @return NULL on error, otherwise IPC channel
  */ 
 struct EXTRACTOR_Channel *
-EXTRACTOR_IPC_channel_create_ (const char *short_libname);
+EXTRACTOR_IPC_channel_create_ (const char *short_libname,
+                              struct EXTRACTOR_SharedMemory *shm);
 
 
 /**
@@ -49,13 +127,67 @@
 
 
 /**
- * Map the given buffer
+ * Send data via the given IPC channel (blocking).
  *
  * @param channel channel to communicate with the plugin
+ * @param buf data to send
+ * @param size number of bytes in buf to send
+ * @return -1 on error, number of bytes sent on success
+ *           (never does partial writes)
  */
-void
-EXTRACTOR_IPC_channel_xxx_ (struct EXTRACTOR_Channel *channel);
+ssize_t
+EXTRACTOR_IPC_channel_send_ (struct EXTRACTOR_Channel *channel,
+                            const void *data,
+                            size_t size);
 
 
+/**
+ * Handler for a message from one of the plugins.
+ *
+ * @param cls closure
+ * @param short_libname library name of the channel sending the message
+ * @param msg header of the message from the plugin
+ * @param value 'data' send from the plugin
+ * @param mime mime string send from the plugin
+ */
+typedef void (*EXTRACTOR_ChannelMessageProcessor) (void *cls,
+                                                  const char *short_libname,
+                                                  const struct IpcHeader *msg,
+                                                  const void *value,
+                                                  const char *mime);
 
+/**
+ * Process a reply from channel (seek request, metadata and done message)
+ *
+ * @param buf buffer with data from IPC channel
+ * @param size number of bytes in buffer
+ * @param proc metadata callback
+ * @param proc_cls callback cls
+ * @return number of bytes processed, -1 on error
+ */
+ssize_t
+EXTRACTOR_IPC_process_reply_ (const void *data,
+                             size_t size,
+                             EXTRACTOR_ChannelMessageProcessor proc,
+                             void *proc_cls);
+
+
+/**
+ * Receive data from any of the given IPC channels (blocking).
+ * Wait for one of the plugins to reply.
+ *
+ * @param channels array of channels, channels that break may be set to NULL
+ * @param num_channels length of the 'channels' array
+ * @param proc function to call to process messages (may be called
+ *             more than once)
+ * @param proc_cls closure for 'proc'
+ * @return -1 on error (i.e. no response in 10s), 1 on success
+ */
+int
+EXTRACTOR_IPC_channel_recv_ (struct EXTRACTOR_Channel **channels,
+                            unsigned int num_channels,
+                            EXTRACTOR_ChannelMessageProcessor proc,
+                            void *proc_cls);
+
+
 #endif

Modified: Extractor/src/main/extractor_ipc_gnu.c
===================================================================
--- Extractor/src/main/extractor_ipc_gnu.c      2012-07-22 14:39:48 UTC (rev 
22821)
+++ Extractor/src/main/extractor_ipc_gnu.c      2012-07-22 18:20:40 UTC (rev 
22822)
@@ -1,6 +1,6 @@
 /*
      This file is part of libextractor.
-     (C) 2002, 2003, 2004, 2005, 2006, 2009, 2012 Vidyut Samanta and Christian 
Grothoff
+     (C) 2012 Vidyut Samanta and Christian Grothoff
 
      libextractor is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
@@ -17,24 +17,51 @@
      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      Boston, MA 02111-1307, USA.
  */
-
+/**
+ * @file main/extractor_ipc_gnu.c
+ * @brief IPC with plugin for GNU/POSIX systems
+ * @author Christian Grothoff
+ */
 #include "platform.h"
 #include "plibc.h"
 #include "extractor.h"
+#include "extractor_datasource.h"
+#include "extractor_ipc.h"
 #include <dirent.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <sys/shm.h>
 #include <signal.h>
 
+/**
+ * Size of the channel buffer; determines largest IPC message that
+ * is going to be allowed.  FIXME: we might want to grow this
+ * buffer dynamically instead...
+ */
+#define CHANNEL_BUFFER_SIZE (1024 * 256)
 
 /**
- * Definition of an IPC communication channel with
- * some plugin.
+ * A shared memory resource (often shared with several
+ * other processes).
  */
-struct EXTRACTOR_Channel
+struct EXTRACTOR_SharedMemory
 {
   /**
+   * Pointer to the mapped region of the shm (covers the whole shm)
+   */ 
+  void *shm_ptr;
+
+  /**
+   * Page size. Mmap offset is a multiple of this number.
+   */
+  long allocation_granularity;
+
+  /**
+   * Allocated size of the shm
+   */ 
+  size_t shm_size;
+
+  /**
    * POSIX id of the shm into which data is uncompressed
    */ 
   int shm;
@@ -44,447 +71,328 @@
    */ 
   char shm_name[MAX_SHM_NAME + 1];
 
+};
+
+
+/**
+ * Definition of an IPC communication channel with
+ * some plugin.
+ */
+struct EXTRACTOR_Channel
+{
+
   /**
-   * Pointer to the mapped region of the shm (covers the whole shm)
-   */ 
-  void *shm_ptr;
+   * Buffer for reading data from the plugin.
+   */
+  char data[CHANNEL_BUFFER_SIZE];
 
   /**
-   * Position within shm
-   */ 
-  int64_t shm_pos;
+   * Memory segment shared with this process.
+   */
+  struct EXTRACTOR_SharedMemory *shm;
 
   /**
-   * Allocated size of the shm
-   */ 
-  int64_t shm_size;
+   * Name of the plugin to use for this channel.
+   */
+  const char *short_libname;
 
   /**
-   * Number of bytes in shm (<= shm_size)
-   */ 
-  size_t shm_buf_size;
+   * Pipe used to communicate information to the plugin child process.
+   * NULL if not initialized.
+   */
+  int cpipe_in;
 
+  /**
+   * Number of valid bytes in the channel's buffer.
+   */
+  size_t size;
 
+  /**
+   * Pipe used to read information about extracted meta data from
+   * the plugin child process.  -1 if not initialized.
+   */
+  int cpipe_out;
+
+  /**
+   * Process ID of the child process for this plugin. 0 for none.
+   */
+  pid_t cpid;
+
 };
 
 
 /**
- * Opens a shared memory object (for later mmapping).
- * This is POSIX variant of the the plugin_open_* function. Shm is always 
memory-backed.
- * Closes a shm is already opened, closes it before opening a new one.
+ * Create a shared memory area.
  *
- * @param plugin plugin context
- * @param shm_name name of the shm.
- * @return shm id (-1 on error). That is, the result of shm_open() syscall.
- */ 
-static int
-plugin_open_shm (struct EXTRACTOR_PluginList *plugin, 
-                const char *shm_name)
+ * @param size size of the shared area
+ * @return NULL on error
+ */
+struct EXTRACTOR_SharedMemory *
+EXTRACTOR_IPC_shared_memory_create_ (size_t size)
 {
-  if (plugin->shm_id != -1)
-    close (plugin->shm_id);
-  plugin->shm_id = shm_open (shm_name, O_RDONLY, 0);
-  return plugin->shm_id;
+  struct EXTRACTOR_SharedMemory *shm;
+  const char *tpath;
+
+  if (NULL == (shm = malloc (sizeof (struct EXTRACTOR_SharedMemory))))
+    return NULL;
+#if SOMEBSD
+  /* this works on FreeBSD, not sure about others... */
+  tpath = getenv ("TMPDIR");
+  if (tpath == NULL)
+    tpath = "/tmp/";
+#else
+  tpath = "/"; /* Linux */
+#endif 
+  snprintf (shm->shm_name,
+           MAX_SHM_NAME, 
+           "%slibextractor-shm-%u-%u", 
+           tpath, getpid (),
+           (unsigned int) RANDOM());
+  if (-1 == (shm->shm_id = shm_open (shm->shm_name,
+                                    O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)))
+    {
+      free (shm);
+      return NULL;
+    }
+  if ( (0 != ftruncate (shm->shm_id, size)) ||
+       (NULL == (shm->shm_ptr = mmap (NULL, size, 
+                                     PROT_WRITE, MAP_SHARED, 
+                                     shm->shm_id, 0))) ||
+       (((void*) -1) == shm->shm_ptr) )
+  {
+    (void) close (shm->shm_id);
+    (void) shm_unlink (shm->shm_name);
+    free (shm);
+    return NULL;
+  }
+  shm->shm_size = size;
+  return shm; 
 }
 
 
 /**
- * Opens a file (for later mmapping).
- * This is POSIX variant of the plugin_open_* function.
- * Closes a file is already opened, closes it before opening a new one.
+ * Destroy shared memory area.
  *
- * @param plugin plugin context
- * @param shm_name name of the file to open.
- * @return file id (-1 on error). That is, the result of open() syscall.
- */ 
-static int
-plugin_open_file (struct EXTRACTOR_PluginList *plugin, 
-                 const char *shm_name)
+ * @param shm memory area to destroy
+ * @return NULL on error
+ */
+void
+EXTRACTOR_IPC_shared_memory_destroy_ (struct EXTRACTOR_SharedMemory *shm)
 {
-  if (plugin->shm_id != -1)
-    close (plugin->shm_id);
-  plugin->shm_id = open (shm_name, O_RDONLY, 0);
-  return plugin->shm_id;
+  munmap (shm->shm_ptr, shm->map_size);
+  (void) close (plugin->shm_id);
+  (void) shm_unlink (shm->shm_name);
+  free (shm);
 }
 
 
 /**
- * Initializes an extracting session for a plugin.
- *   opens the file/shm (only in OPMODE_FILE)
- *   sets shm_ptr to NULL (unmaps it, if it was mapped)
- *   sets position to 0
- *   initializes file size to 'fsize' (may be -1)
- *   sets seek request to 0
+ * Initialize shared memory area from data source.
  *
- * @param plugin plugin context
- * @param operation_mode the mode of operation (OPMODE_*)
- * @param fsize size of the source file (may be -1)
- * @param shm_name name of the shm or file to open
- * @return 0 on success, non-0 on error.
- */ 
-static int
-init_state_method (struct EXTRACTOR_PluginList *plugin, 
-                  uint8_t operation_mode, 
-                  int64_t fsize, 
-                  const char *shm_name)
+ * @param shm memory area to initialize
+ * @param ds data source to use for initialization
+ * @param off offset to use in data source
+ * @param size number of bytes to copy
+ * @return -1 on error, otherwise number of bytes copied
+ */
+ssize_t
+EXTRACTOR_IPC_shared_memory_set_ (struct EXTRACTOR_SharedMemory *shm,
+                                 struct EXTRACTOR_Datasource *ds,
+                                 uint64_t off,
+                                 size_t size)
 {
-  plugin->seek_request = 0;
-  if (plugin->shm_ptr != NULL)
-    munmap (plugin->shm_ptr, plugin->map_size);
-  plugin->shm_ptr = NULL;
-  if (operation_mode == OPMODE_FILE)
-  {
-    if (-1 == plugin_open_file (plugin, shm_name))
-      return 1;
-  }
-  else if (-1 == plugin_open_shm (plugin, shm_name))
-    return 1;
-  plugin->fsize = fsize;
-  plugin->shm_pos = 0;
-  plugin->fpos = 0;
-  return 0;
+  if (-1 ==
+      EXTRACTOR_datasource_seek_ (ds, off, SEEK_SET))
+    return -1;
+  if (size > shm->map_size)
+    size = shm->map_size;
+  return EXTRACTOR_datasource_read_ (ds,
+                                    shm->shm_ptr,
+                                    size);
 }
 
 
 /**
- * Deinitializes an extracting session for a plugin.
- *   unmaps shm_ptr (if was mapped)
- *   closes file/shm (if it was opened)
- *   sets map size and shm_ptr to NULL.
+ * Create a channel to communicate with a process wrapping
+ * the plugin of the given name.  Starts the process as well.
  *
- * @param plugin plugin context
+ * @param short_libname name of the plugin
+ * @param shm memory to share with the process
+ * @return NULL on error, otherwise IPC channel
  */ 
-static void
-discard_state_method (struct EXTRACTOR_PluginList *plugin)
+struct EXTRACTOR_Channel *
+EXTRACTOR_IPC_channel_create_ (const char *short_libname,
+                              struct EXTRACTOR_SharedMemory *shm)
 {
-  if (plugin->shm_ptr != NULL && plugin->map_size > 0)
-    munmap (plugin->shm_ptr, plugin->map_size);
-  if (plugin->shm_id != -1)
-    close (plugin->shm_id);
-  plugin->shm_id = -1;
-  plugin->map_size = 0;
-  plugin->shm_ptr = NULL;
-}
-
-
-
-/**
- * Start the process for the given plugin.
- */ 
-static void
-start_process (struct EXTRACTOR_PluginList *plugin)
-{
+  struct EXTRACTOR_Channel *channel;
   int p1[2];
   int p2[2];
   pid_t pid;
   int status;
 
-  switch (plugin->flags)
-  {
-  case EXTRACTOR_OPTION_DEFAULT_POLICY:
-    if (-1 != plugin->cpid && 0 != plugin->cpid)
-      return;
-    break;
-  case EXTRACTOR_OPTION_OUT_OF_PROCESS_NO_RESTART:
-    if (0 != plugin->cpid)
-      return;
-    break;
-  case EXTRACTOR_OPTION_IN_PROCESS:
-    return;
-    break;
-  case EXTRACTOR_OPTION_DISABLED:
-    return;
-    break;
-  }
-
-  plugin->cpid = -1;
+  if (NULL == (channel = malloc (sizeof (struct EXTRACTOR_Channel))))
+    return NULL;
+  channel->shm = shm;
+  channel->short_libname = short_libname;
   if (0 != pipe (p1))
-  {
-    plugin->flags = EXTRACTOR_OPTION_DISABLED;
-    return;
-  }
+    {
+      free (channel);
+      return NULL;
+    }
   if (0 != pipe (p2))
-  {
-    close (p1[0]);
-    close (p1[1]);
-    plugin->flags = EXTRACTOR_OPTION_DISABLED;
-    return;
-  }
+    {
+      (void) close (p1[0]);
+      (void) close (p1[1]);
+      free (channel);
+      return;
+    }
   pid = fork ();
-  plugin->cpid = pid;
   if (pid == -1)
-  {
-    close (p1[0]);
-    close (p1[1]);
-    close (p2[0]);
-    close (p2[1]);
-    plugin->flags = EXTRACTOR_OPTION_DISABLED;
-    return;
-  }
-  if (pid == 0)
-  {
-    close (p1[1]);
-    close (p2[0]);
-    plugin_main (plugin, p1[0], p2[1]);
-    _exit (0);
-  }
-  close (p1[0]);
-  close (p2[1]);
-  plugin->cpipe_in = fdopen (p1[1], "w");
-  if (plugin->cpipe_in == NULL)
-  {
-    perror ("fdopen");
-    (void) kill (plugin->cpid, SIGKILL);
-    waitpid (plugin->cpid, &status, 0);
-    close (p1[1]);
-    close (p2[0]);
-    plugin->cpid = -1;
-    plugin->flags = EXTRACTOR_OPTION_DISABLED;
-    return;
-  }
-  plugin->cpipe_out = p2[0];
+    {
+      (void) close (p1[0]);
+      (void) close (p1[1]);
+      (void) close (p2[0]);
+      (void) close (p2[1]);
+      free (channel);
+      return NULL;
+    }
+  if (0 == pid)
+    {
+      (void) close (p1[1]);
+      (void) close (p2[0]);
+      EXTRACTOR_plugin_main_ (short_libname, p1[0], p2[1]);
+      _exit (0);
+    }
+  (void) close (p1[0]);
+  (void) close (p2[1]);
+  channel->cpipe_in = p1[1];
+  channel->cpipe_out = p2[0];
+  channel->cpid = pid;
+  return channel;
 }
 
 
 /**
- * Stop the child process of this plugin.
+ * Destroy communication channel with a plugin/process.  Also
+ * destroys the process.
+ *
+ * @param channel channel to communicate with the plugin
  */
-static void
-stop_process (struct EXTRACTOR_PluginList *plugin)
+void
+EXTRACTOR_IPC_channel_destroy_ (struct EXTRACTOR_Channel *channel)
 {
   int status;
 
-#if DEBUG
-  if (plugin->cpid == -1)
-    fprintf (stderr,
-            "Plugin `%s' choked on this input\n",
-            plugin->short_libname);
-#endif
-  if ( (plugin->cpid == -1) ||
-       (plugin->cpid == 0) )
-    return;
-  kill (plugin->cpid, SIGKILL);
-  waitpid (plugin->cpid, &status, 0);
-  plugin->cpid = -1;
-  close (plugin->cpipe_out);
-  fclose (plugin->cpipe_in);
-  plugin->cpipe_out = -1;
-  plugin->cpipe_in = NULL;
-
-  if (plugin->flags != EXTRACTOR_OPTION_DEFAULT_POLICY)
-    plugin->flags = EXTRACTOR_OPTION_DISABLED;
-
-  plugin->seek_request = -1;
+  (void) kill (channel->cpid, SIGKILL);
+  (void) waitpid (channel->cpid, &status, 0);
+  (void) close (channel->cpipe_out);
+  (void) close (channel->cpipe_in);
+  free (channel);
 }
 
 
-static int
-write_plugin_data (const struct EXTRACTOR_PluginList *plugin)
-{
-  /* This function is only necessary on W32. On POSIX
-   * systems plugin inherits its own data from the parent */
-  return 0;
-}
-
-
 /**
- * Initializes an extracting session for a plugin.
- *   opens the file/shm (only in OPMODE_FILE)
- *   sets shm_ptr to NULL (unmaps it, if it was mapped)
- *   sets position to 0
- *   initializes file size to 'fsize' (may be -1)
- *   sets seek request to 0
+ * Send data via the given IPC channel (blocking).
  *
- * @param plugin plugin context
- * @param operation_mode the mode of operation (OPMODE_*)
- * @param fsize size of the source file (may be -1)
- * @param shm_name name of the shm or file to open
- * @return 0 on success, non-0 on error.
- */ 
-static int
-init_state_method (struct EXTRACTOR_PluginList *plugin, 
-                  uint8_t operation_mode, 
-                  int64_t fsize, 
-                  const char *shm_name)
-{
-  plugin->seek_request = 0;
-  if (plugin->shm_ptr != NULL)
-    munmap (plugin->shm_ptr, plugin->map_size);
-  plugin->shm_ptr = NULL;
-  if (operation_mode == OPMODE_FILE)
-  {
-    if (-1 == plugin_open_file (plugin, shm_name))
-      return 1;
-  }
-  else if (-1 == plugin_open_shm (plugin, shm_name))
-    return 1;
-  plugin->fsize = fsize;
-  plugin->shm_pos = 0;
-  plugin->fpos = 0;
-  return 0;
-}
-
-
-/**
- * Setup a shared memory segment.
- *
- * @param ptr set to the location of the shm segment
- * @param shmid where to store the shm ID
- * @param fn name of the shared segment
- * @param fn_size size available in fn
- * @param size number of bytes to allocated for the segment
- * @return 0 on success
+ * @param channel channel to communicate with the plugin
+ * @param buf data to send
+ * @param size number of bytes in buf to send
+ * @return -1 on error, number of bytes sent on success
+ *           (never does partial writes)
  */
-static int
-make_shm_posix (void **ptr, 
-               int *shmid, 
-               char *fn, 
-               size_t fn_size, size_t size)
+ssize_t
+EXTRACTOR_IPC_channel_send_ (struct EXTRACTOR_Channel *channel,
+                            const void *data,
+                            size_t size)
 {
-  const char *tpath;
-#if SOMEBSD
-  /* this works on FreeBSD, not sure about others... */
-  tpath = getenv ("TMPDIR");
-  if (tpath == NULL)
-    tpath = "/tmp/";
-#else
-  tpath = "/"; /* Linux */
-#endif 
-  snprintf (fn, fn_size, "%slibextractor-shm-%u-%u", tpath, getpid(),
-      (unsigned int) RANDOM());
-  *shmid = shm_open (fn, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
-  *ptr = NULL;
-  if (-1 == *shmid)
-    return 1;
-  if ((0 != ftruncate (*shmid, size)) ||
-      (NULL == (*ptr = mmap (NULL, size, PROT_WRITE, MAP_SHARED, *shmid, 0))) 
||
-      (*ptr == (void*) -1) )
-  {
-    close (*shmid);
-    *shmid = -1;
-    shm_unlink (fn);
-    return 1;
-  }
-  return 0;
-}
+  const char *cdata = data;
+  size_t off = 0;
+  ssize_t ret;
 
-
-static void
-destroy_shm_posix (void *ptr, int shm_id, size_t size, char *shm_name)
-{
-  if (NULL != ptr)
-    munmap (ptr, size);
-  if (shm_id != -1)
-    close (shm_id);
-  shm_unlink (shm_name);
+  while (off < size)
+    {
+      ret = write (channel->cpipe_in, &cdata[off], size - off);
+      if (ret <= 0)
+       return -1;
+      off += ret;
+    }
+  return size;
 }
 
 
 /**
- * Receive 'size' bytes from plugin, store them in 'buf'
- *
- * @param plugin plugin context
- * @param buf buffer to fill
- * @param size number of bytes to read
- * @return number of bytes read, 0 on EOS, < 0 on error
- */
-static int
-plugin_read (struct EXTRACTOR_PluginList *plugin, 
-            void *buf, 
-            size_t size)
-{
-  char *rb = buf;
-  ssize_t read_result;
-  size_t read_count = 0;
-
-  while (read_count < size)
-  {
-    read_result = read (plugin->cpipe_out, 
-                       &rb[read_count], size - read_count);
-    if (read_result <= 0)
-      return read_result;
-    read_count += read_result;
-  }
-  return read_count;
-}
-
-
-/**
+ * Receive data from any of the given IPC channels (blocking).
  * Wait for one of the plugins to reply.
- * Selects on plugin output pipes, runs receive_reply()
+ * Selects on plugin output pipes, runs 'receive_reply'
  * on each activated pipe until it gets a seek request
  * or a done message. Called repeatedly by the user until all pipes are dry or
  * broken.
  *
- * @param plugins to select upon
- * @param proc metadata callback
- * @param proc_cls callback cls
- * @return number of dry/broken pipes since last call, -1 on error or if no
- *         plugins reply in 10 seconds.
+ * @param channels array of channels, channels that break may be set to NULL
+ * @param num_channels length of the 'channels' array
+ * @param proc function to call to process messages (may be called
+ *             more than once)
+ * @param proc_cls closure for 'proc'
+ * @return -1 on error, 1 on success
  */
-static int
-wait_for_reply (struct EXTRACTOR_PluginList *plugins,
-               EXTRACTOR_MetaDataProcessor proc, void *proc_cls)
+int
+EXTRACTOR_IPC_channel_recv_ (struct EXTRACTOR_Channel **channels,
+                            unsigned int num_channels,
+                            EXTRACTOR_ChannelMessageProcessor proc,
+                            void *proc_cls)
 {
-  int ready;
-  int result;
   struct timeval tv;
   fd_set to_check;
-  int highest = 0;
-  int read_result;
-  struct EXTRACTOR_PluginList *ppos;
+  int max;
+  unsigned int i;
+  struct EXTRACTOR_Channel *channel;
+  ssize_t ret;
+  ssize_t iret;
 
   FD_ZERO (&to_check);
-  for (ppos = plugins; NULL != ppos; ppos = ppos->next)
+  max = -1;
+  for (i=0;i<num_channels;i++)
     {
-      switch (ppos->flags)
-       {
-       case EXTRACTOR_OPTION_DEFAULT_POLICY:
-       case EXTRACTOR_OPTION_OUT_OF_PROCESS_NO_RESTART:
-         if (ppos->seek_request == -1)
-           continue;
-         FD_SET (ppos->cpipe_out, &to_check);
-         if (highest < ppos->cpipe_out)
-           highest = ppos->cpipe_out;
-         break;
-       case EXTRACTOR_OPTION_IN_PROCESS:
-         break;
-       case EXTRACTOR_OPTION_DISABLED:
-         break;
-       }
+      channel = channels[i];
+      if (NULL == channel)
+       continue;
+      FD_SET (channel->cpipe_out, &to_check);
+      if (max < channel->cpipe_out)
+       max = channel->cpipe_out;
     }
-  
   tv.tv_sec = 10;
   tv.tv_usec = 0;
-  ready = select (highest + 1, &to_check, NULL, NULL, &tv);
-  if (ready <= 0)
-    /* an error or timeout -> something's wrong or all plugins hung up */
-    return -1;
-
-  result = 0;
-  for (ppos = plugins; NULL != ppos; ppos = ppos->next)
+  if (-1 == select (max + 1, &to_check, NULL, NULL, &tv))
     {
-      switch (ppos->flags)
+      /* an error or timeout -> something's wrong or all plugins hung up */
+      return -1;
+    }
+  for (i=0;i<num_channels;i++)
+    {
+      channel = channels[i];
+      if (NULL == channel)
+       continue;
+      if (! FD_ISSET (channel->cpipe_out, &to_check))
+       continue;
+      if ( (-1 == (iret = read (channel->cpipe_out,
+                               &channel->data[channel->size],
+                               CHANNEL_BUFFER_SIZE - channel->size)) ) ||
+          (ret = EXTRACTOR_IPC_process_reply_ (channel->data, 
+                                               channel->size + iret, 
+                                               proc, proc_cls)) )
        {
-       case EXTRACTOR_OPTION_DEFAULT_POLICY:
-       case EXTRACTOR_OPTION_OUT_OF_PROCESS_NO_RESTART:
-         if (ppos->seek_request == -1)
-           continue;
-         if (FD_ISSET (ppos->cpipe_out, &to_check))
-           {
-             read_result = receive_reply (ppos, proc, proc_cls);
-             if (read_result < 0)
-               {
-                 stop_process (ppos);
-               }
-             result += 1;
-           }
-         break;
-       case EXTRACTOR_OPTION_IN_PROCESS:
-         break;
-       case EXTRACTOR_OPTION_DISABLED:
-         break;
+         EXTRACTOR_IPC_channel_destroy (channel);
+         channels[i] = NULL;
        }
+      else
+       {
+         memmove (channel->data,
+                  &channel->data[ret],
+                  channel->size + iret - ret);
+         channel->size = channel->size + iret - ret;
+       }
     }
-  return result;
+  return 1;
 }
+
+/* end of extractor_ipc_gnu.c */

Modified: Extractor/src/main/extractor_ipc_w32.c
===================================================================
--- Extractor/src/main/extractor_ipc_w32.c      2012-07-22 14:39:48 UTC (rev 
22821)
+++ Extractor/src/main/extractor_ipc_w32.c      2012-07-22 18:20:40 UTC (rev 
22822)
@@ -20,10 +20,8 @@
 
 
 /**
- * Definition of an IPC communication channel with
- * some plugin.
  */
-struct EXTRACTOR_Channel
+struct EXTRACTOR_SharedMemory
 {
 
   /**
@@ -60,7 +58,58 @@
 };
 
 
+/**
+ * Definition of an IPC communication channel with
+ * some plugin.
+ */
+struct EXTRACTOR_Channel
+{
 
+  /**
+   * Process ID of the child process for this plugin. 0 for none.
+   */
+  HANDLE hProcess;
+
+  /**
+   * Pipe used to communicate information to the plugin child process.
+   * NULL if not initialized.
+   */
+  HANDLE cpipe_in;
+
+  /**
+   * Handle of the shm object
+   */
+  HANDLE map_handle;
+
+  /**
+   * Pipe used to read information about extracted meta data from
+   * the plugin child process.  -1 if not initialized.
+   */
+  HANDLE cpipe_out;
+
+  /**
+   * Page size. Mmap offset is a multiple of this number.
+   */
+  DWORD allocation_granularity;
+
+  /**
+   * A structure for overlapped reads on W32.
+   */
+  OVERLAPPED ov_read;
+
+  /**
+   * A structure for overlapped writes on W32.
+   */
+  OVERLAPPED ov_write;
+
+  /**
+   * A write buffer for overlapped writes on W32
+   */
+  unsigned char *ov_write_buffer;
+
+};
+
+
 /**
  * Initializes an extracting session for a plugin.
  *   opens the file/shm (only in OPMODE_FILE)
@@ -437,71 +486,6 @@
 
 
 /**
- * Reads plugin data from the LE server process.
- * Also initializes allocation granularity (duh...).
- *
- * @param fd the pipe to read from
- *
- * @return newly allocated plugin context
- */ 
-static struct EXTRACTOR_PluginList *
-read_plugin_data (int fd)
-{
-  struct EXTRACTOR_PluginList *ret;
-  size_t i;
-
-  ret = malloc (sizeof (struct EXTRACTOR_PluginList));
-  if (ret == NULL)
-    return NULL;
-  read (fd, &i, sizeof (size_t));
-  ret->libname = malloc (i);
-  if (ret->libname == NULL)
-  {
-    free (ret);
-    return NULL;
-  }
-  read (fd, ret->libname, i);
-  ret->libname[i - 1] = '\0';
-
-  read (fd, &i, sizeof (size_t));
-  ret->short_libname = malloc (i);
-  if (ret->short_libname == NULL)
-  {
-    free (ret->libname);
-    free (ret);
-    return NULL;
-  }
-  read (fd, ret->short_libname, i);
-  ret->short_libname[i - 1] = '\0';
-
-  read (fd, &i, sizeof (size_t));
-  if (i == 0)
-  {
-    ret->plugin_options = NULL;
-  }
-  else
-  {
-    ret->plugin_options = malloc (i);
-    if (ret->plugin_options == NULL)
-    {
-      free (ret->short_libname);
-      free (ret->libname);
-      free (ret);
-      return NULL;
-    }
-    read (fd, ret->plugin_options, i);
-    ret->plugin_options[i - 1] = '\0';
-  }
-  {
-    SYSTEM_INFO si;
-    GetSystemInfo (&si);
-    ret->allocation_granularity = si.dwAllocationGranularity;
-  }
-  return ret;
-}
-
-
-/**
  * Start the process for the given plugin.
  */ 
 static void
@@ -513,7 +497,8 @@
   PROCESS_INFORMATION proc;
   char cmd[MAX_PATH + 1];
   char arg1[10], arg2[10];
-  HANDLE p10_os_inh = INVALID_HANDLE_VALUE, p21_os_inh = INVALID_HANDLE_VALUE;
+  HANDLE p10_os_inh = INVALID_HANDLE_VALUE;
+  HANDLE p21_os_inh = INVALID_HANDLE_VALUE;
   SECURITY_ATTRIBUTES sa;
 
   switch (plugin->flags)
@@ -614,6 +599,35 @@
 
 
 /**
+ * Receive 'size' bytes from channel, store them in 'buf'
+ *
+ * @param plugin plugin context
+ * @param buf buffer to fill
+ * @param size number of bytes to read
+ * @return number of bytes read, 0 on EOS, < 0 on error
+ */
+static int
+plugin_read (struct EXTRACTOR_PluginList *plugin, 
+            void *buf, 
+            size_t size)
+{
+  char *rb = buf;
+  ssize_t read_result;
+  size_t read_count = 0;
+
+  while (read_count < size)
+  {
+    read_result = read (plugin->cpipe_out, 
+                       &rb[read_count], size - read_count);
+    if (read_result <= 0)
+      return read_result;
+    read_count += read_result;
+  }
+  return read_count;
+}
+
+
+/**
  * Stop the child process of this plugin.
  */
 static void
@@ -731,38 +745,6 @@
 #define plugin_write(plug, buf, size) write_all (fileno (plug->cpipe_in), buf, 
size)
 
 
-void CALLBACK 
-RundllEntryPoint (HWND hwnd, 
-                 HINSTANCE hinst, 
-                 LPSTR lpszCmdLine, 
-                 int nCmdShow)
-{
-  intptr_t in_h;
-  intptr_t out_h;
-  int in;
-  int out;
-
-  sscanf (lpszCmdLine, "%lu %lu", &in_h, &out_h);
-  in = _open_osfhandle (in_h, _O_RDONLY);
-  out = _open_osfhandle (out_h, 0);
-  setmode (in, _O_BINARY);
-  setmode (out, _O_BINARY);
-  plugin_main (read_plugin_data (in),
-              in, out);
-}
-
-
-void CALLBACK 
-RundllEntryPointA (HWND hwnd, 
-                  HINSTANCE hinst, 
-                  LPSTR lpszCmdLine, 
-                  int nCmdShow)
-{
-  return RundllEntryPoint (hwnd, hinst, lpszCmdLine, nCmdShow);
-}
-
-
-
 /**
  * Receive 'size' bytes from plugin, store them in 'buf'
  *

Added: Extractor/src/main/extractor_plugin_main.c
===================================================================
--- Extractor/src/main/extractor_plugin_main.c                          (rev 0)
+++ Extractor/src/main/extractor_plugin_main.c  2012-07-22 18:20:40 UTC (rev 
22822)
@@ -0,0 +1,625 @@
+/*
+     This file is part of libextractor.
+     (C) 2012 Vidyut Samanta and Christian Grothoff
+
+     libextractor 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 3, or (at your
+     option) any later version.
+
+     libextractor 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 libextractor; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+ */
+/**
+ * @file main/extractor_plugin_main.c
+ * @brief main loop for an out-of-process plugin
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include "plibc.h"
+#include "extractor.h"
+#include "extractor_datasource.h"
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/shm.h>
+#include <signal.h>
+
+
+
+/**
+ * Opens a file (for later mmapping).
+ * This is POSIX variant of the plugin_open_* function.
+ * Closes a file is already opened, closes it before opening a new one.
+ * Destroy shared memory area.
+ *
+ * @param plugin plugin context
+ * @param shm_name name of the file to open.
+ * @return file id (-1 on error). That is, the result of open() syscall.
+ */ 
+static int
+plugin_open_file (struct EXTRACTOR_PluginList *plugin, 
+                 const char *shm_name)
+{
+  if (plugin->shm_id != -1)
+    close (plugin->shm_id);
+  plugin->shm_id = open (shm_name, O_RDONLY, 0);
+  return plugin->shm_id;
+}
+
+
+/**
+ * Moves current absolute buffer position to @pos in @whence mode.
+ * Will move logical position withouth shifting the buffer, if possible.
+ * Will not move beyond the end of file.
+ *
+ * @param plugin plugin context
+ * @param pos position to move to
+ * @param whence seek mode (SEEK_CUR, SEEK_SET, SEEK_END)
+ * @return new absolute position, -1 on error
+ */
+static int64_t
+pl_seek (struct EXTRACTOR_PluginList *plugin, int64_t pos, int whence)
+{
+  switch (whence)
+  {
+  case SEEK_CUR:
+    if (plugin->shm_pos + pos < plugin->map_size && plugin->shm_pos + pos >= 0)
+    {
+      plugin->shm_pos += pos;
+      return plugin->fpos + plugin->shm_pos;
+    }
+    if (0 != pl_pick_next_buffer_at (plugin, plugin->fpos + plugin->shm_pos + 
pos, 1))
+      return -1;
+    plugin->shm_pos += pos;
+    return plugin->fpos + plugin->shm_pos;
+    break;
+  case SEEK_SET:
+    if (pos < 0)
+      return -1;
+    if (pos >= plugin->fpos && pos < plugin->fpos + plugin->map_size)
+    {
+      plugin->shm_pos = pos - plugin->fpos;
+      return pos;
+    }
+    if (0 != pl_pick_next_buffer_at (plugin, pos, 1))
+      return -1;
+    if (pos >= plugin->fpos && pos < plugin->fpos + plugin->map_size)
+    {
+      plugin->shm_pos = pos - plugin->fpos;
+      return pos;
+    }
+    return -1;
+    break;
+  case SEEK_END:
+    while (plugin->fsize == -1)
+    {
+      pl_pick_next_buffer_at (plugin, plugin->fpos + plugin->map_size + pos, 
0);
+    }
+    if (plugin->fsize + pos - 1 < plugin->fpos || plugin->fsize + pos - 1 > 
plugin->fpos + plugin->map_size)
+    {
+      if (0 != pl_pick_next_buffer_at (plugin, plugin->fsize - MAX_READ, 0))
+        return -1;
+    }
+    plugin->shm_pos = plugin->fsize + pos - plugin->fpos;
+    if (plugin->shm_pos < 0)
+      plugin->shm_pos = 0;
+    else if (plugin->shm_pos >= plugin->map_size)
+      plugin->shm_pos = plugin->map_size - 1;
+    return plugin->fpos + plugin->shm_pos - 1;
+    break;
+  }
+  return -1;
+}
+
+
+static int64_t
+pl_get_fsize (struct EXTRACTOR_PluginList *plugin)
+{
+  return plugin->fsize;
+}
+
+
+/**
+ * Fills @data with a pointer to the data buffer.
+ * Equivalent to read(), except you don't have to allocate and free
+ * a buffer, since the data is already in memory.
+ * Will move the buffer, if necessary
+ *
+ * @param plugin plugin context
+ * @param data location to store data pointer
+ * @param count number of bytes to read
+ * @return number of bytes (<= count) avalable in @data, -1 on error
+ */
+static int64_t
+pl_read (struct EXTRACTOR_PluginList *plugin, unsigned char **data, size_t 
count)
+{
+  *data = NULL;
+  if (count > MAX_READ)
+    return -1;
+  if (count > plugin->map_size - plugin->shm_pos)
+  {
+    int64_t actual_count;
+    if (plugin->fpos + plugin->shm_pos != pl_seek (plugin, plugin->fpos + 
plugin->shm_pos, SEEK_SET))
+      return -1;
+    *data = &plugin->shm_ptr[plugin->shm_pos];
+    actual_count = (count < plugin->map_size - plugin->shm_pos) ? count : 
(plugin->map_size - plugin->shm_pos);
+    plugin->shm_pos += actual_count;
+    return actual_count;
+  }
+  else
+  {
+    *data = &plugin->shm_ptr[plugin->shm_pos];
+    plugin->shm_pos += count;
+    return count;
+  }
+}
+
+
+/**
+ * Initializes an extracting session for a plugin.
+ *   opens the file/shm (only in OPMODE_FILE)
+ *   sets shm_ptr to NULL (unmaps it, if it was mapped)
+ *   sets position to 0
+ *   initializes file size to 'fsize' (may be -1)
+ *   sets seek request to 0
+ *
+ * @param plugin plugin context
+ * @param operation_mode the mode of operation (OPMODE_*)
+ * @param fsize size of the source file (may be -1)
+ * @param shm_name name of the shm or file to open
+ * @return 0 on success, non-0 on error.
+ */ 
+static int
+init_state_method (struct EXTRACTOR_PluginList *plugin, 
+                  uint8_t operation_mode, 
+                  int64_t fsize, 
+                  const char *shm_name)
+{
+  plugin->seek_request = 0;
+  if (plugin->shm_ptr != NULL)
+    munmap (plugin->shm_ptr, plugin->map_size);
+  plugin->shm_ptr = NULL;
+  if (operation_mode == OPMODE_FILE)
+  {
+    if (-1 == plugin_open_file (plugin, shm_name))
+      return 1;
+  }
+  else if (-1 == plugin_open_shm (plugin, shm_name))
+    return 1;
+  plugin->fsize = fsize;
+  plugin->shm_pos = 0;
+  plugin->fpos = 0;
+  return 0;
+}
+
+
+/**
+ * Function called by a plugin in a child process.  Transmits
+ * the meta data back to the parent process.
+ *
+ * @param cls closure, "int*" of the FD for transmission
+ * @param plugin_name name of the plugin that produced this value;
+ *        special values can be used (i.e. '<zlib>' for zlib being
+ *        used in the main libextractor library and yielding
+ *        meta data).
+ * @param type libextractor-type describing the meta data
+ * @param format basic format information about data 
+ * @param data_mime_type mime-type of data (not of the original file);
+ *        can be NULL (if mime-type is not known)
+ * @param data actual meta-data found
+ * @param data_len number of bytes in data
+ * @return 0 to continue extracting, 1 to abort (transmission error)
+ */ 
+static int
+transmit_reply (void *cls,
+               const char *plugin_name,
+               enum EXTRACTOR_MetaType type,
+               enum EXTRACTOR_MetaFormat format,
+               const char *data_mime_type,
+               const char *data,
+               size_t data_len)
+{
+  static const unsigned char meta_byte = MESSAGE_META;
+  int *cpipe_out = cls;
+  struct IpcHeader hdr;
+  size_t mime_len;
+
+  if (NULL == data_mime_type)
+    mime_len = 0;
+  else
+    mime_len = strlen (data_mime_type) + 1;
+  if (mime_len > MAX_MIME_LEN)
+    mime_len = MAX_MIME_LEN;
+  hdr.meta_type = type;
+  hdr.meta_format = format;
+  hdr.data_len = data_len;
+  hdr.mime_len = mime_len;
+  if ( (sizeof (meta_byte) != 
+       write_all (*cpipe_out,
+                  &meta_byte, sizeof (meta_byte))) ||
+       (sizeof (hdr) != 
+       write_all (*cpipe_out, 
+                  &hdr, sizeof (hdr))) ||
+       (mime_len !=
+       write_all (*cpipe_out, 
+                  data_mime_type, mime_len)) ||
+       (data_len !=
+       write_all (*cpipe_out, 
+                  data, data_len)) )
+    return 1;
+  return 0;
+}
+
+
+/**
+ * Main loop function for plugins.  Reads a message from the plugin
+ * input pipe and acts on it.
+ *
+ * @param plugin plugin context
+ * @param in input stream with incoming requests
+ * @param out output stream for sending responses
+ */ 
+static void
+process_requests (struct EXTRACTOR_PluginList *plugin,
+                 int in,
+                 int out)
+{
+  int read_result1;
+  int read_result2;
+  int read_result3;
+  int read_result4;
+  unsigned char code;
+  char *shm_name = NULL;
+  size_t shm_name_len;
+  int extract_reply;
+  struct IpcHeader hdr;
+  int do_break;
+#ifdef WINDOWS
+  HANDLE map;
+  MEMORY_BASIC_INFORMATION mi;
+#endif
+
+  /* The point of recursing into this function is to request
+   * a seek from LE server and wait for a reply. This snipper
+   * requests a seek.
+   */
+  if (plugin->waiting_for_update == 1)
+  {
+    unsigned char seek_byte = MESSAGE_SEEK;
+    if (write (out, &seek_byte, 1) != 1)
+      return -1;
+    if (write (out, &plugin->seek_request, sizeof (int64_t)) != sizeof 
(int64_t))
+      return -1;
+  }
+
+  memset (&hdr, 0, sizeof (hdr));
+  do_break = 0;
+  while (!do_break)
+  {
+    read_result1 = read (in, &code, 1);
+    if (read_result1 <= 0)
+      break;
+    switch (code)
+    {
+    case MESSAGE_INIT_STATE:
+      read_result2 = read (in, &plugin->operation_mode, sizeof (uint8_t));
+      read_result3 = read (in, &plugin->fsize, sizeof (int64_t));
+      read_result4 = read (in, &shm_name_len, sizeof (size_t));
+      if ((read_result2 < sizeof (uint8_t)) ||
+          (read_result3 < sizeof (int64_t)) ||
+          (read_result4 < sizeof (size_t)))
+      {
+        do_break = 1;
+        break;
+      }
+      if (plugin->operation_mode != OPMODE_MEMORY &&
+          plugin->operation_mode != OPMODE_DECOMPRESS &&
+          plugin->operation_mode != OPMODE_FILE)
+      {
+        do_break = 1;
+        break;
+      }
+      if ((plugin->operation_mode == OPMODE_MEMORY ||
+          plugin->operation_mode == OPMODE_DECOMPRESS) &&
+          shm_name_len > MAX_SHM_NAME)
+      {
+        do_break = 1;
+        break;
+      }
+      /* Fsize may be -1 only in decompression mode */
+      if (plugin->operation_mode != OPMODE_DECOMPRESS && plugin->fsize <= 0)
+      {
+        do_break = 1;
+        break;
+      }
+      if (shm_name != NULL)
+        free (shm_name);
+      shm_name = malloc (shm_name_len);
+      if (shm_name == NULL)
+      {
+        do_break = 1;
+        break;
+      }
+      read_result2 = read (in, shm_name, shm_name_len);
+      if (read_result2 < shm_name_len)
+      {
+        do_break = 1;
+        break;
+      }
+      shm_name[shm_name_len - 1] = '\0';
+      do_break = init_state_method (plugin, plugin->operation_mode, 
plugin->fsize, shm_name);
+      /* in OPMODE_MEMORY and OPMODE_FILE we can start extracting right away,
+       * there won't be UPDATED_SHM message, and we don't need it
+       */
+      if (!do_break && (plugin->operation_mode == OPMODE_MEMORY ||
+          plugin->operation_mode == OPMODE_FILE))
+      {
+        extract_reply = plugin->extract_method (plugin, transmit_reply, &out);
+        unsigned char done_byte = MESSAGE_DONE;
+        if (write (out, &done_byte, 1) != 1)
+        {
+          do_break = 1;
+          break;
+        }
+        if ((plugin->specials != NULL) &&
+            (NULL != strstr (plugin->specials, "force-kill")))
+        {
+          /* we're required to die after each file since this
+             plugin only supports a single file at a time */
+#if !WINDOWS
+          fsync (out);
+#else
+          _commit (out);
+#endif
+          _exit (0);
+        }
+      }
+      break;
+    case MESSAGE_DISCARD_STATE:
+      discard_state_method (plugin);
+      break;
+    case MESSAGE_UPDATED_SHM:
+      if (plugin->operation_mode == OPMODE_DECOMPRESS)
+      {
+        read_result2 = read (in, &plugin->fpos, sizeof (int64_t));
+        read_result3 = read (in, &plugin->map_size, sizeof (size_t));
+        read_result4 = read (in, &plugin->fsize, sizeof (int64_t));
+        if ((read_result2 < sizeof (int64_t)) || (read_result3 < sizeof 
(size_t)) ||
+            plugin->fpos < 0 || (plugin->operation_mode != OPMODE_DECOMPRESS 
&& (plugin->fsize <= 0 || plugin->fpos >= plugin->fsize)))
+        {
+          do_break = 1;
+          break;
+        }
+        /* FIXME: also check mapped region size (lseek for *nix, VirtualQuery 
for W32) */
+        /* Re-map the shm */
+#if !WINDOWS
+        if ((-1 == plugin->shm_id) ||
+            (NULL == (plugin->shm_ptr = mmap (NULL, plugin->map_size, 
PROT_READ, MAP_SHARED, plugin->shm_id, 0))) ||
+            (plugin->shm_ptr == (void *) -1))
+        {
+          do_break = 1;
+          break;
+        }
+#else
+        if ((plugin->map_handle == 0) ||
+           (NULL == (plugin->shm_ptr = MapViewOfFile (plugin->map_handle, 
FILE_MAP_READ, 0, 0, 0))))
+        {
+          do_break = 1;
+          break;
+        }
+#endif
+        if (plugin->waiting_for_update == 1)
+        {
+          /* We were only waiting for this one message */
+          do_break = 1;
+          plugin->waiting_for_update = 2;
+          break;
+        }
+        /* Run extractor on mapped region (recursive call doesn't reach this
+         * point and breaks out earlier.
+         */
+        extract_reply = plugin->extract_method (plugin, transmit_reply, &out);
+        /* Unmap the shm */
+#if !WINDOWS
+        if ((plugin->shm_ptr != NULL) &&
+            (plugin->shm_ptr != (void*) -1) )
+          munmap (plugin->shm_ptr, plugin->map_size);
+#else
+        if (plugin->shm_ptr != NULL)
+          UnmapViewOfFile (plugin->shm_ptr);
+#endif
+        plugin->shm_ptr = NULL;
+        if (extract_reply == 1)
+        {
+          /* Tell LE that we're done */
+          unsigned char done_byte = MESSAGE_DONE;
+          if (write (out, &done_byte, 1) != 1)
+          {
+            do_break = 1;
+            break;
+          }
+          if ((plugin->specials != NULL) &&
+              (NULL != strstr (plugin->specials, "force-kill")))
+          {
+            /* we're required to die after each file since this
+               plugin only supports a single file at a time */
+#if !WINDOWS
+            fsync (out);
+#else
+            _commit (out);
+#endif
+            _exit (0);
+          }
+        }
+        else
+        {
+          /* Tell LE that we're not done, and we need to seek */
+          unsigned char seek_byte = MESSAGE_SEEK;
+          if (write (out, &seek_byte, 1) != 1)
+          {
+            do_break = 1;
+            break;
+          }
+          if (write (out, &plugin->seek_request, sizeof (int64_t)) != sizeof 
(int64_t))
+          {
+            do_break = 1;
+            break;
+          }
+        }
+      }
+      else
+      {
+        /* This is mostly to safely skip unrelated messages */
+        int64_t t;
+        size_t t2;
+        read_result2 = read (in, &t, sizeof (int64_t));
+        read_result3 = read (in, &t2, sizeof (size_t));
+        read_result4 = read (in, &t, sizeof (int64_t));
+      }
+      break;
+    }
+  }
+  return 0;
+}
+
+
+/**
+ * 'main' function of the child process. Loads the plugin,
+ * sets up its in and out pipes, then runs the request serving function.
+ *
+ * @param plugin extractor plugin to use
+ * @param in stream to read from
+ * @param out stream to write to
+ */
+void
+EXTRACTOR_plugin_main_ (struct EXTRACTOR_PluginList *plugin, 
+                       int in, int out)
+{
+  if (0 != EXTRACTOR_plugin_load_ (plugin))
+    {
+#if DEBUG
+      fprintf (stderr, "Plugin `%s' failed to load!\n", plugin->short_libname);
+#endif
+      return;
+    }  
+  if ( (NULL != plugin->specials) &&
+       (NULL != strstr (plugin->specials, "close-stderr")))
+    close (2);
+  if ( (NULL != plugin->specials) &&
+       (NULL != strstr (plugin->specials, "close-stdout")))
+    close (1);
+  process_requests (plugin, in, out);
+}
+
+
+#if WINDOWS
+/**
+ * Reads plugin data from the LE server process.
+ * Also initializes allocation granularity (duh...).
+ *
+ * @param fd the pipe to read from
+ * @return newly allocated plugin context
+ */ 
+static struct EXTRACTOR_PluginList *
+read_plugin_data (int fd)
+{
+  struct EXTRACTOR_PluginList *ret;
+  SYSTEM_INFO si;
+  size_t i;
+
+  if (NULL == (ret = malloc (sizeof (struct EXTRACTOR_PluginList))))
+    return NULL;
+  GetSystemInfo (&si);
+  ret->allocation_granularity = si.dwAllocationGranularity;
+  read (fd, &i, sizeof (size_t));
+  if (NULL == (ret->libname = malloc (i)))
+    {
+      free (ret);
+      return NULL;
+    }
+  read (fd, ret->libname, i);
+  ret->libname[i - 1] = '\0';
+  read (fd, &i, sizeof (size_t));
+  if (NULL == (ret->short_libname = malloc (i)))
+    {
+      free (ret->libname);
+      free (ret);
+      return NULL;
+    }
+  read (fd, ret->short_libname, i);
+  ret->short_libname[i - 1] = '\0';
+  read (fd, &i, sizeof (size_t));
+  if (0 == i)
+    {
+      ret->plugin_options = NULL;
+      return ret;
+    }
+  if (NULL == (ret->plugin_options = malloc (i)))
+    {
+      free (ret->short_libname);
+      free (ret->libname);
+      free (ret);
+      return NULL;
+    }
+  read (fd, ret->plugin_options, i);
+  ret->plugin_options[i - 1] = '\0';
+  return ret;
+}
+
+
+/**
+ * FIXME: document.
+ */
+void CALLBACK 
+RundllEntryPoint (HWND hwnd, 
+                 HINSTANCE hinst, 
+                 LPSTR lpszCmdLine, 
+                 int nCmdShow)
+{
+  struct EXTRACTOR_PluginList *plugin;
+  intptr_t in_h;
+  intptr_t out_h;
+  int in;
+  int out;
+
+  sscanf (lpszCmdLine, "%lu %lu", &in_h, &out_h);
+  in = _open_osfhandle (in_h, _O_RDONLY);
+  out = _open_osfhandle (out_h, 0);
+  setmode (in, _O_BINARY);
+  setmode (out, _O_BINARY);
+  if (NULL == (plugin = read_plugin_data (in)))
+    {
+      close (in);
+      close (out);
+      return;
+    }
+  plugin_main (plugin,
+              in, out);
+  close (in);
+  close (out);
+}
+
+
+/**
+ * FIXME: document.
+ */
+void CALLBACK 
+RundllEntryPointA (HWND hwnd, 
+                  HINSTANCE hinst, 
+                  LPSTR lpszCmdLine, 
+                  int nCmdShow)
+{
+  return RundllEntryPoint (hwnd, hinst, lpszCmdLine, nCmdShow);
+}
+
+
+#endif

Added: Extractor/src/main/extractor_plugin_main.h
===================================================================
--- Extractor/src/main/extractor_plugin_main.h                          (rev 0)
+++ Extractor/src/main/extractor_plugin_main.h  2012-07-22 18:20:40 UTC (rev 
22822)
@@ -0,0 +1,43 @@
+/*
+     This file is part of libextractor.
+     (C) 2012 Vidyut Samanta and Christian Grothoff
+
+     libextractor 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 3, or (at your
+     option) any later version.
+
+     libextractor 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 libextractor; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+ */
+/**
+ * @file main/extractor_plugin_main.c
+ * @brief main loop for an out-of-process plugin
+ * @author Christian Grothoff
+ */
+#ifndef EXTRACTOR_PLUGIN_MAIN_H
+#define EXTRACTOR_PLUGIN_MAIN_H
+
+#include "extractor.h"
+
+
+/**
+ * 'main' function of the child process. Loads the plugin,
+ * sets up its in and out pipes, then runs the request serving function.
+ *
+ * @param plugin extractor plugin to use
+ * @param in stream to read from
+ * @param out stream to write to
+ */
+void
+EXTRACTOR_plugin_main_ (struct EXTRACTOR_PluginList *plugin, 
+                       int in, int out);
+
+#endif

Modified: Extractor/src/main/extractor_plugins.c
===================================================================
--- Extractor/src/main/extractor_plugins.c      2012-07-22 14:39:48 UTC (rev 
22821)
+++ Extractor/src/main/extractor_plugins.c      2012-07-22 18:20:40 UTC (rev 
22822)
@@ -4,7 +4,7 @@
 
      libextractor 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, or (at your
+     by the Free Software Foundation; either version 3, or (at your
      option) any later version.
 
      libextractor is distributed in the hope that it will be useful, but
@@ -17,6 +17,11 @@
      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      Boston, MA 02111-1307, USA.
  */
+/**
+ * @file main/extractor_plugins.c
+ * @brief code to load plugins
+ * @author Christian Grothoff
+ */
 #include "extractor_plugins.h"
 #include "extractor_plugpath.h"
 
@@ -330,7 +335,7 @@
        default:
          abort ();
        }
-      if (cpy[last] == '-')
+      if ('-' == cpy[last])
        {
          last++;
          prev = EXTRACTOR_plugin_remove (prev, 

Modified: Extractor/src/main/extractor_plugins.h
===================================================================
--- Extractor/src/main/extractor_plugins.h      2012-07-22 14:39:48 UTC (rev 
22821)
+++ Extractor/src/main/extractor_plugins.h      2012-07-22 18:20:40 UTC (rev 
22822)
@@ -4,7 +4,7 @@
 
      libextractor 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, or (at your
+     by the Free Software Foundation; either version 3, or (at your
      option) any later version.
 
      libextractor is distributed in the hope that it will be useful, but
@@ -17,17 +17,17 @@
      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      Boston, MA 02111-1307, USA.
  */
-
+/**
+ * @file main/extractor_plugins.h
+ * @brief code to load plugins
+ * @author Christian Grothoff
+ */
 #ifndef EXTRACTOR_PLUGINS_H
 #define EXTRACTOR_PLUGINS_H
 
 #include "platform.h"
 #include "plibc.h"
 #include "extractor.h"
-#ifndef WINDOWS
-#include <sys/wait.h>
-#include <sys/shm.h>
-#endif
 #include <signal.h>
 #include <ltdl.h>
 
@@ -47,7 +47,7 @@
   /**
    * Pointer to the plugin (as returned by lt_dlopen).
    */
-  void * libraryHandle;
+  void *libraryHandle;
 
   /**
    * Name of the library (i.e., 'libextractor_foo.so')
@@ -82,122 +82,12 @@
   enum EXTRACTOR_Options flags;
 
   /**
-   * Process ID of the child process for this plugin. 0 for none.
-   */
-#if !WINDOWS
-  int cpid;
-#else
-  HANDLE hProcess;
-#endif
-
-  /**
-   * Pipe used to communicate information to the plugin child process.
-   * NULL if not initialized.
-   */
-#if !WINDOWS
-  FILE *cpipe_in;
-#else
-  HANDLE cpipe_in;
-#endif
-
-  /**
-   * Pipe used by plugin to read from its parent.
-   */
-  int pipe_in;
-
-  /**
    * A position this plugin wants us to seek to. -1 if it's finished.
    * Starts at 0;
    */
   int64_t seek_request;
 
-#if !WINDOWS
   /**
-   * ID of the shm object
-   */
-  int shm_id;
-#else
-  /**
-   * Handle of the shm object
-   */
-  HANDLE map_handle;
-#endif
-
-  /**
-   * Used to pass cfs pointer to in-process plugin in OPMODE_DECOMPRESS
-   */
-  void *pass_cfs;
-
-  /**
-   * Uncompressed stream size. Initially -1, until file is fully decompressed
-   * (for sources that are not compressed it is set from the start).
-   */
-  int64_t fsize;
-
-  /**
-   * Absolute position within the stream
-   */
-  int64_t fpos;
-
-  /**
-   * Pointer to the shared memory segment
-   */
-  unsigned char *shm_ptr;
-
-  /**
-   * Number of bytes in the segment
-   */
-  int64_t map_size;
-
-  /**
-   * Position within the segment
-   */
-  int64_t shm_pos;
-
-#if !WINDOWS
-  /**
-   * Pipe used to read information about extracted meta data from
-   * the plugin child process.  -1 if not initialized.
-   */
-  int cpipe_out;
-#else
-  /**
-   * Pipe used to read information about extracted meta data from
-   * the plugin child process.  -1 if not initialized.
-   */
-  HANDLE cpipe_out;
-#endif
-
-#if !WINDOWS
-  /**
-   * Page size. Mmap offset is a multiple of this number.
-   */
-  long allocation_granularity;
-#else
-  /**
-   * Page size. Mmap offset is a multiple of this number.
-   */
-  DWORD allocation_granularity;
-#endif
-
-#if WINDOWS
-  /**
-   * A structure for overlapped reads on W32.
-   */
-  OVERLAPPED ov_read;
-
-  /**
-   * A structure for overlapped writes on W32.
-   */
-  OVERLAPPED ov_write;
-
-  /**
-   * A write buffer for overlapped writes on W32
-   */
-  unsigned char *ov_write_buffer;
-#endif
-
-  /**
    * Mode of operation. One of the OPMODE_* constants
    */
   uint8_t operation_mode;

Modified: Extractor/src/main/extractor_plugpath.c
===================================================================
--- Extractor/src/main/extractor_plugpath.c     2012-07-22 14:39:48 UTC (rev 
22821)
+++ Extractor/src/main/extractor_plugpath.c     2012-07-22 18:20:40 UTC (rev 
22822)
@@ -4,7 +4,7 @@
 
      libextractor 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, or (at your
+     by the Free Software Foundation; either version 3, or (at your
      option) any later version.
 
      libextractor is distributed in the hope that it will be useful, but
@@ -17,6 +17,11 @@
      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      Boston, MA 02111-1307, USA.
  */
+/**
+ * @file main/extractor_plugpath.c
+ * @brief determine path where plugins are installed
+ * @author Christian Grothoff
+ */
 
 #include "platform.h"
 #include "plibc.h"

Modified: Extractor/src/main/extractor_plugpath.h
===================================================================
--- Extractor/src/main/extractor_plugpath.h     2012-07-22 14:39:48 UTC (rev 
22821)
+++ Extractor/src/main/extractor_plugpath.h     2012-07-22 18:20:40 UTC (rev 
22822)
@@ -1,3 +1,27 @@
+/*
+     This file is part of libextractor.
+     (C) 2002, 2003, 2004, 2005, 2006, 2009, 2012 Vidyut Samanta and Christian 
Grothoff
+
+     libextractor 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 3, or (at your
+     option) any later version.
+
+     libextractor 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 libextractor; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+ */
+/**
+ * @file main/extractor_plugpath.h
+ * @brief determine path where plugins are installed
+ * @author Christian Grothoff
+ */
 #ifndef EXTRACTOR_PLUGPATH_H
 #define EXTRACTOR_PLUGPATH_H
 
@@ -7,8 +31,8 @@
  * @param cls closure
  * @param path a directory path
  */
-typedef void (*EXTRACTOR_PathProcessor)(void *cls,
-                                       const char *path);
+typedef void (*EXTRACTOR_PathProcessor) (void *cls,
+                                        const char *path);
 
 
 /**




reply via email to

[Prev in Thread] Current Thread [Next in Thread]