Enlightenment CVS committal

Author  : onefang
Project : e17
Module  : libs/ecore

Dir     : e17/libs/ecore/src/lib/ecore


Modified Files:
        ecore_exe.c 


Log Message:
The fork'n'pipe knows line dancing!

Er, I mean line buffering.

It's slightly different from what raster wanted.  I'll update the example next.

===================================================================
RCS file: /cvsroot/enlightenment/e17/libs/ecore/src/lib/ecore/ecore_exe.c,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -3 -r1.23 -r1.24
--- ecore_exe.c 11 Dec 2005 06:52:07 -0000      1.23
+++ ecore_exe.c 16 Dec 2005 03:36:16 -0000      1.24
@@ -127,12 +127,15 @@
  *
  * This function does the same thing as ecore_exe_run(), but also makes the
  * standard in and/or out from the child process available for reading or
- * writing. To write use ecore_exe_pipe_write(). To read listen to 
- * ECORE_EVENT_EXE_DATA events (set up a handler). Ecore may buffer read data
- * until a newline character if asked for with the @p flags. All data will be
- * included in the events (newlines will not be stripped). This will only
- * happen if the process is run with ECORE_EXE_PIPE_READ enabled in the flags.
- * 
+ * writing.  To write use ecore_exe_pipe_write().  To read listen to
+ * ECORE_EVENT_EXE_DATA events (set up a handler).  Ecore may buffer read
+ * data until a newline character if asked for with the @p flags.  All
+ * data will be included in the events (newlines will be replaced with
+ * NULLS if line buffered).  ECORE_EVENT_EXE_DATA events will only happen
+ * if the process is run with ECORE_EXE_PIPE_READ enabled in the flags.
+ * Writing will only be allowed with ECORE_EXE_PIPE_WRITE enabled in the
+ * flags.
+ *
  * @param   exe_cmd The command to run with @c /bin/sh.
  * @param   flags   The flag parameters for how to deal with inter-process I/O
  * @param   data    Data to attach to the returned process handle.
@@ -142,6 +145,7 @@
 Ecore_Exe *
 ecore_exe_pipe_run(const char *exe_cmd, Ecore_Exe_Flags flags, const void 
*data)
 {
+/* FIXME: MAybe we should allow STDERR reading as well. */
    Ecore_Exe *exe = NULL;
    pid_t pid = 0;
    int readPipe[2] = { -1, -1 };
@@ -658,73 +662,120 @@
    exe = data;
    if ((exe->read_fd_handler) && 
(ecore_main_fd_handler_active_get(exe->read_fd_handler, ECORE_FD_READ)))
       {
-         unsigned char *inbuf = NULL;
-        int inbuf_num = 0;
+         unsigned char *inbuf;
+        int inbuf_num;
+
+         inbuf = exe->read_data_buf;
+         inbuf_num = exe->read_data_size;
+        exe->read_data_buf = NULL;
+        exe->read_data_size = 0;
 
         for (;;)
            {
-              int num, lost_server;
+              int num, lost_exe;
               char buf[READBUFSIZ];
 
-              lost_server = 0;
+              lost_exe = 0;
               errno = 0;
-              if ((num = read(exe->child_fd_read, buf, READBUFSIZ)) < 1)
+              if ((num = read(exe->child_fd_read, buf, READBUFSIZ)) < 1)  /* 
FIXME: SPEED/SIZE TRADE OFF - add a smaller READBUFSIZE (currently 64k) to 
inbuf, use that instead of buf, and save ourselves a memcpy(). */
                  {
-                    lost_server = ((errno == EIO) || 
-                                   (errno == EBADF) ||
-                                   (errno == EPIPE) || 
-                                   (errno == EINVAL) ||
-                                   (errno == ENOSPC) || 
-                                   (num == 0));
-                      /* is num == 0 is right - when the server closes us 
-                       * off we will get this (as this is called when select
-                       * tells us there is data to read!)
-                       */
+                    lost_exe = ((errno == EIO) || 
+                                (errno == EBADF) ||
+                                (errno == EPIPE) || 
+                                (errno == EINVAL) ||
+                                (errno == ENOSPC));
                      if ((errno != EAGAIN) && (errno != EINTR))
                         perror("_ecore_exe_data_handler() read problem ");
                   }
-              if (num < 1)
-              {
-                 if (inbuf) 
-                    {
-                       Ecore_Event_Exe_Data *e;
+              if (num > 0)
+                 {
+                    inbuf = realloc(inbuf, inbuf_num + num);
+                    memcpy(inbuf + inbuf_num, buf, num);
+                    inbuf_num += num;
+                 }
+              else
+                 {
+                    if (inbuf) 
+                       {
+                          Ecore_Event_Exe_Data *e;
                       
-                       e = calloc(1, sizeof(Ecore_Event_Exe_Data));
-                       if (e)
-                          {
-                             e->exe = exe;
-                             e->data = inbuf;
-                             e->size = inbuf_num;
-                             ecore_event_add(ECORE_EVENT_EXE_DATA, e,
+                          e = calloc(1, sizeof(Ecore_Event_Exe_Data));
+                          if (e)
+                             {
+                                e->exe = exe;
+                                e->data = inbuf;
+                                e->size = inbuf_num;
+
+                                 if (exe->flags & 
ECORE_EXE_PIPE_READ_LINE_BUFFERED)
+                                   {
+                                      int max = 0;
+                                      int count = 0;
+                                      int i;
+                                      int last = 0;
+                                      char *c;
+
+                                       c = inbuf;
+                                      for (i = 0; i < inbuf_num; i++) /* Find 
the lines. */
+                                         {
+                                            if (inbuf[i] == '\n')
+                                               {
+                                                  if (count >= max)
+                                                     {
+                                                        max += 10;  /* FIXME: 
Maybe keep track of the largest number of lines ever sent, and add half that 
many instead of 10. */
+                                                        e->lines = 
realloc(e->lines, sizeof(Ecore_Event_Exe_Data_Line) * (max + 1)); /* Allow room 
for the NULL termination. */
+                                                     }
+                                                  /* raster said to leave the 
line endings as line endings, however -
+                                                   * This is line buffered 
mode, we are not dealing with binary here, but lines.
+                                                   * If we are not dealing 
with binary, we must be dealing with ASCII, unicode, or some other text format.
+                                                   * Thus the user is most 
likely gonna deal with this text as strings.
+                                                   * Thus the user is most 
likely gonna pass this data to str functions.
+                                                   * rasters way - the endings 
are always gonna be '\n';  onefangs way - they will always be '\0'
+                                                   * We are handing them the 
string length as a convenience.
+                                                   * Thus if they really want 
it in raw format, they can e->lines[i].line[e->lines[i].size - 1] = '\n'; 
easily enough.
+                                                   * In the default case, we 
can do this conversion quicker than the user can, as we already have the index 
and pointer.
+                                                   * Let's make it easy on 
them to use these as standard C strings.
+                                                   *
+                                                   * onefang is proud to 
announce that he has just set a new personal record for the
+                                                   * most over documentation 
of a simple assignment statement.  B-)
+                                                   */
+                                                  inbuf[i] = '\0';
+                                                  e->lines[count].line = c;
+                                                  e->lines[count].size = i - 
last;
+                                                  last = i + 1;
+                                                  c = &inbuf[last];
+                                                  count++;
+                                               }
+                                         }
+                                         if (count == 0) /* No lines to send, 
cancel the event. */
+                                            {
+                                                
_ecore_exe_event_exe_data_free(NULL, e);
+                                               e = NULL;
+                                            }
+                                         else /* NULL terminate the array, so 
that people know where the end is. */
+                                            {
+                                               e->lines[count].line = NULL;
+                                               e->lines[count].size = 0;
+                                            }
+                                         if (i > last) /* Partial line left 
over, save it for next time. */
+                                            {
+                                               e->size = last;
+                                               exe->read_data_size = i - last;
+                                               exe->read_data_buf = 
malloc(exe->read_data_size);
+                                               memcpy(exe->read_data_buf, c, 
exe->read_data_size);
+                                            }
+                                   }
+
+                                if (e)
+                                   ecore_event_add(ECORE_EVENT_EXE_DATA, e,
                                            _ecore_exe_event_exe_data_free, 
NULL);
-                          }
-                    }
-                 if (lost_server)
-                    {
-                       /* we lost our server! */
+                             }
+                       }
+                    if (lost_exe)
                         ecore_exe_terminate(exe);
-                       return 1;
-                    }
-                 break;
-              }
-           else
-              {
-                  inbuf = realloc(inbuf, inbuf_num + num);
-                  memcpy(inbuf + inbuf_num, buf, num);
-                  inbuf_num += num;
-   /* FIXME: 
-    * when fd handlers report data - if line buffering is not enabled instantly
-    * copy data to a exe data event struct and add the event like ecore_con. if
-    * line buffering is enabled, parse new data block for a \n. if there is
-    * none, then simply append to read buf. if there are 1 or more, append
-    * until, and including the first \n, to the existing read buf (if any) then
-    * generate data event for that. repeat for each other \n found until no \n
-    * chars are left, then take trailing data (if any) and put in read buf
-    * waiting for more data.
-    */
-              }
-         }
-     }
+                    break;
+                 }
+           }
+      }
 
    return 1;
 }
@@ -785,7 +836,9 @@
    Ecore_Event_Exe_Data *e;
 
    e = ev;
-   if (e->data) free(e->data);
+
+   if (e->lines)   free(e->lines);
+   if (e->data)    free(e->data);
    free(e);
 }
 #endif




-------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
for problems?  Stop!  Download the new AJAX search engine that makes
searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
http://ads.osdn.com/?ad_id=7637&alloc_id=16865&op=click
_______________________________________________
enlightenment-cvs mailing list
enlightenment-cvs@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-cvs

Reply via email to