Browse Source

Working buffers / timeouts.

This changes everything.  Instead
of working with c null term strings,
everything moves to using char * +
length.

We can now handle null values in the
buffer.

One of the bugs was in mangler.
It can no longer use the buffer --
because we process the buffer in
chunks ending in "\r\n"!
(It now has own buffer [2K].)

If we insert, we overwrite the pending/
buffered data.
bugz 4 years ago
parent
commit
1b60b2a1bf
1 changed files with 255 additions and 93 deletions
  1. 255 93
      mystic.cpp

+ 255 - 93
mystic.cpp

@@ -197,6 +197,24 @@ int randrange(int M, int N) {
   return M + rand() / (RAND_MAX / (N - M + 1) + 1);
   return M + rand() / (RAND_MAX / (N - M + 1) + 1);
 }
 }
 
 
+/*
+ * strnstr()
+ *
+ * buffer safe version that looks for a string.
+ */
+const char *strnstr(const char *source, int len, const char *needle) {
+  int pos;
+
+  for (pos = 0; pos < len; pos++) {
+    if (source[pos] == needle[0]) {
+      if (strncmp(source + pos, needle, strlen(needle)) == 0) {
+        return source + pos;
+      }
+    }
+  }
+  return NULL;
+}
+
 /*
 /*
 What is the name of the actual, real Mystic executable
 What is the name of the actual, real Mystic executable
 that we'll be executing and mangling?
 that we'll be executing and mangling?
@@ -204,7 +222,7 @@ that we'll be executing and mangling?
 
 
 #define TARGET "./mySTIC"
 #define TARGET "./mySTIC"
 // Size of our input and output buffers.
 // Size of our input and output buffers.
-#define BSIZE 128
+#define BSIZE 1024
 
 
 /*
 /*
  * string_insert()
  * string_insert()
@@ -1016,21 +1034,23 @@ void render_effect(int fd, char ch) {
  * Handles TRIGGER.
  * Handles TRIGGER.
  * Renders with effects.
  * Renders with effects.
  */
  */
-void render(int fd, const char *string_out) {
+void render(int fd, const char *string_out, int len) {
   const char *cp = string_out;
   const char *cp = string_out;
   const char *trigger = cp;
   const char *trigger = cp;
+
   time_t start = time(NULL);
   time_t start = time(NULL);
   int elapsed;
   int elapsed;
   int over = 0;
   int over = 0;
 
 
   reset_render();
   reset_render();
 
 
-  ZF_LOGV("render(%d, %s)", fd, repr(string_out));
+  // ZF_LOGV("render(%d, %s)", fd, repr(string_out));
+  ZF_LOGV_MEM(string_out, len, "render(%d, %d bytes):", fd, len);
 
 
   // Check our time from time to time.
   // Check our time from time to time.
   // If we start running long, disable sleeps.
   // If we start running long, disable sleeps.
 
 
-  while ((trigger = strstr(cp, TRIGGER)) != NULL) {
+  while ((trigger = strnstr(cp, len - (cp - trigger), TRIGGER)) != NULL) {
     // There is special things to handle in here.
     // There is special things to handle in here.
     while (cp != trigger) {
     while (cp != trigger) {
       elapsed = time(NULL) - start;
       elapsed = time(NULL) - start;
@@ -1054,7 +1074,7 @@ void render(int fd, const char *string_out) {
   };
   };
 
 
   // We still might be under a rendering effect.
   // We still might be under a rendering effect.
-  while (*cp != 0) {
+  while (cp < (string_out + len)) {
     elapsed = time(NULL) - start;
     elapsed = time(NULL) - start;
     if (elapsed > SLEEP_LIMIT) {
     if (elapsed > SLEEP_LIMIT) {
       render_overlimit = 1;
       render_overlimit = 1;
@@ -1126,7 +1146,7 @@ void harry_idle_event(int fd) {
 
 
   sprintf(buffer, "^S2^C%02d%s^P2^CR^D%02d", color, cp, (int)strlen(cp));
   sprintf(buffer, "^S2^C%02d%s^P2^CR^D%02d", color, cp, (int)strlen(cp));
   ZF_LOGD("harry_event: render(%d, \"%s\")", fd, buffer);
   ZF_LOGD("harry_event: render(%d, \"%s\")", fd, buffer);
-  render(fd, buffer);
+  render(fd, buffer, strlen(buffer));
 }
 }
 
 
 void init_harry() {
 void init_harry() {
@@ -1228,7 +1248,7 @@ int regmatch(regex_t *preg, const char *string, size_t nmatch,
 
 
   while (matches < nmatch) {
   while (matches < nmatch) {
     int ret = regexec(preg, string + offset, nmatch - matches, pmatch + matches,
     int ret = regexec(preg, string + offset, nmatch - matches, pmatch + matches,
-                  eflags);
+                      eflags);
     if (!ret) {
     if (!ret) {
       int current = offset;
       int current = offset;
       offset += pmatch[matches].rm_eo;
       offset += pmatch[matches].rm_eo;
@@ -1393,27 +1413,45 @@ int word_mangler(char *buffer, int len) {
   return count;
   return count;
 }
 }
 
 
+int buffer_insert(char *buffer, int len, int max_length, int pos,
+                  const char *insert) {
+  if (len + strlen(insert) > max_length) {
+    ZF_LOGD("buffer_insert failed [%s]", repr(insert));
+    return 0;
+  }
+  memmove(buffer + pos + strlen(insert), buffer + pos, len - pos);
+  strncpy(buffer + pos, insert, strlen(insert));
+  return 1;
+}
+
 /*
 /*
  * The buffer that we've been given is much larger now.
  * The buffer that we've been given is much larger now.
  *
  *
+ * We can no longer mangle or insert into the given buffer.
+ * Why?  Because we don't know what is behind it now!
  */
  */
-int mangle(int fd, char *buffer) {
+int mangle(int fd, const char *buffer, int len) {
   int x, i;
   int x, i;
   int need_render = 0; // changing word case around doesn't need the render
   int need_render = 0; // changing word case around doesn't need the render
   int mangled = 0;
   int mangled = 0;
   int mangled_chars = 0;
   int mangled_chars = 0;
+  char play[2048];
+  const char *cp;
 
 
-  char *cp;
+  memcpy(play, buffer, len);
+
+  // NEVER reference buffer from this point on!
 
 
   // Ok, we want to look for words to:
   // Ok, we want to look for words to:
   // MaNGlE , or transpose (both?!)
   // MaNGlE , or transpose (both?!)
   // or possibly transpose words
   // or possibly transpose words
-  char work[(BSIZE * 4) + 1];
+  char work[2048];
 
 
   // Use terminal - clean out ANSI
   // Use terminal - clean out ANSI
 
 
-  ZF_LOGI("mangle:");
-  ZF_LOGI_REPR(buffer);
+  // ZF_LOGI("mangle:");
+  ZF_LOGI_MEM(play, len, "Mangle (%u bytes):", len);
+
   // strcpy(work, buffer);
   // strcpy(work, buffer);
 
 
   /*
   /*
@@ -1430,7 +1468,7 @@ int mangle(int fd, char *buffer) {
       display ANSI graphic file, with delays ... then CLS
       display ANSI graphic file, with delays ... then CLS
    */
    */
   const char *ANSI_CLS = "\x1b[2J";
   const char *ANSI_CLS = "\x1b[2J";
-  cp = strstr(buffer, ANSI_CLS);
+  cp = strnstr(play, len, ANSI_CLS); // strstr(buffer, ANSI_CLS);
 
 
   if (cp != NULL) {
   if (cp != NULL) {
     static int ANSI_CLS_count = 0; // count the number we've seen
     static int ANSI_CLS_count = 0; // count the number we've seen
@@ -1445,7 +1483,7 @@ int mangle(int fd, char *buffer) {
       // Make exact copy of our current console state.
       // Make exact copy of our current console state.
       memcpy(&temp_console, &console, sizeof(console));
       memcpy(&temp_console, &console, sizeof(console));
       // Play the buffer into the console
       // Play the buffer into the console
-      console_receive(&temp_console, buffer, cp - buffer);
+      console_receive(&temp_console, play, cp - play);
       char restore_color[30]; // ansi color
       char restore_color[30]; // ansi color
       strcpy(restore_color, color_restore(&temp_console));
       strcpy(restore_color, color_restore(&temp_console));
 
 
@@ -1457,11 +1495,10 @@ int mangle(int fd, char *buffer) {
           const char *filename;
           const char *filename;
           int cls;
           int cls;
           int rand_pos;
           int rand_pos;
-        } possibles[] = {{"goofy_head", 1, 0}, {"bat", 1, 0},
-                         {"panther", 1, 0},    {"wolf", 1, 0},
-                         {"skull", 0, 1},      {"skull2", 0, 1},
-                         {"guy", 0, 1},        {"blinkman", 0, 1},
-                         {"ghost", 1, 0}};
+        } possibles[] = {
+            {"goofy_head", 1, 0}, {"bat", 1, 0},      {"panther", 1, 0},
+            {"wolf", 1, 0},       {"skull", 0, 1},    {"skull2", 0, 1},
+            {"guy", 0, 1},        {"blinkman", 0, 1}, {"ghost", 1, 0}};
 
 
         //          bat.ans       creature.ans  goofy_head.ans  panther.ans
         //          bat.ans       creature.ans  goofy_head.ans  panther.ans
         //          skull.ans       ghost.ans
         //          skull.ans       ghost.ans
@@ -1501,18 +1538,23 @@ int mangle(int fd, char *buffer) {
         ZF_LOGI("mangle(ANSI_CLS): %d file inserted %s", r, repr(display));
         ZF_LOGI("mangle(ANSI_CLS): %d file inserted %s", r, repr(display));
 
 
         // Move the buffer so there's room for the display string.
         // Move the buffer so there's room for the display string.
-        if (string_insert(buffer, BSIZE * 4, cp - buffer, display)) {
-          ZF_LOGI("mangle(ANSI_CLS):");
-          ZF_LOGI_REPR(buffer);
-          ZF_LOGI("mangle(ANSI_CLS): [%s]", repr(buffer));
+        if (buffer_insert(play, len, sizeof(play), cp - play, display)) {
+          len += strlen(display);
+          // if (string_insert(buffer, 1024, cp - buffer, display)) {
+
+          ZF_LOGI_MEM(play, len, "mangle(ANSI_CLS) (%u bytes):", len);
+          // ZF_LOGI("mangle(ANSI_CLS):");
+          // ZF_LOGI_REPR(buffer);
+          // ZF_LOGI("mangle(ANSI_CLS): [%s]", repr(buffer));
           need_render = 1;
           need_render = 1;
 
 
           /*
           /*
           Copy the new buffer over, but hide our "render" code
           Copy the new buffer over, but hide our "render" code
           from the remaining mangler steps.
           from the remaining mangler steps.
           */
           */
-          strcpy(work, buffer);
-          i = cp - buffer;
+          memcpy(work, play, len);
+          // strcpy(work, buffer);
+          i = cp - play;
           // find offset into "buffer"
           // find offset into "buffer"
           // apply to work.
           // apply to work.
           memset(work + i, ' ', strlen(display));
           memset(work + i, ' ', strlen(display));
@@ -1563,20 +1605,27 @@ int mangle(int fd, char *buffer) {
 
 
           // sprintf(display, "^P1^S3^C%02d%s^S0^R0%s^P1", color, phrasing[r],
           // sprintf(display, "^P1^S3^C%02d%s^S0^R0%s^P1", color, phrasing[r],
           // restore_color);
           // restore_color);
-          ZF_LOGI("mangle(ANSI_CLS): Inserted (%02d) %s", color, phrasing[r]);
+          // ZF_LOGI("mangle(ANSI_CLS): Inserted (%02d) %s", color,
+          // phrasing[r]);
+          ZF_LOGI_MEM(play, len, "mangle(ANSI_CLS) :");
 
 
           // Move the buffer so there's room for the display string.
           // Move the buffer so there's room for the display string.
-          if (string_insert(buffer, BSIZE * 4, cp - buffer, display)) {
-            ZF_LOGI("mangle(ANSI_CLS):");
-            ZF_LOGI_REPR(buffer);
+          if (buffer_insert(play, len, 1024, cp - play, display)) {
+            len += strlen(display);
+
+            // if (string_insert(buffer, BSIZE * 4, cp - buffer, display)) {
+            ZF_LOGI_MEM(play, len, "mangle(ANSI_CLS) + :");
+            // ZF_LOGI("mangle(ANSI_CLS):");
+            // ZF_LOGI_REPR(buffer);
             need_render = 1;
             need_render = 1;
 
 
             /*
             /*
             Copy the new buffer over, but hide our "render" code
             Copy the new buffer over, but hide our "render" code
             from the remaining mangler steps.
             from the remaining mangler steps.
             */
             */
-            strcpy(work, buffer);
-            i = cp - buffer;
+            memcpy(work, play, len);
+            // strcpy(work, buffer);
+            i = cp - play;
             // find offset into "buffer"
             // find offset into "buffer"
             // apply to work.
             // apply to work.
             memset(work + i, ' ', strlen(display));
             memset(work + i, ' ', strlen(display));
@@ -1589,19 +1638,30 @@ int mangle(int fd, char *buffer) {
     }
     }
   }
   }
 
 
-  strcpy(work, buffer); // sure.
+  memcpy(work, play, len);
+
+  // strcpy(work, buffer); // sure.
 
 
   const char replace_with = ' ';
   const char replace_with = ' ';
-  for (x = 0; x < strlen(buffer); x++) {
-    int ansi = console_char(&console, buffer[x]);
+  for (x = 0; x < len; x++) {
+    int ansi = console_char(&console, play[x]);
     if (ansi) {
     if (ansi) {
       work[x] = replace_with;
       work[x] = replace_with;
     }
     }
+    // fixup "work" so it's a valid C string
+    if (buffer[x] == 0) {
+      work[x] = replace_with;
+    }
   }
   }
+  // fixup "work" buffer so it's a valid c string
+  work[len] = 0;
 
 
+  ZF_LOGI_MEM(work, len, "Work now:");
+  /*
   ZF_LOGD("work now:");
   ZF_LOGD("work now:");
   ZF_LOGD_REPR(work);
   ZF_LOGD_REPR(work);
   ZF_LOGD("Work Now: [%s]", repr(work));
   ZF_LOGD("Work Now: [%s]", repr(work));
+  */
 
 
 #ifdef OLD_WAY
 #ifdef OLD_WAY
 
 
@@ -1632,7 +1692,7 @@ int mangle(int fd, char *buffer) {
 
 
       // Yes!  Be random!
       // Yes!  Be random!
       if (random_activate(8)) {
       if (random_activate(8)) {
-        int c = word_mangler(buffer + rxmatch[i].rm_so,
+        int c = word_mangler(play + rxmatch[i].rm_so,
                              rxmatch[i].rm_eo - rxmatch[i].rm_so);
                              rxmatch[i].rm_eo - rxmatch[i].rm_so);
         if (c) {
         if (c) {
           mangled++;
           mangled++;
@@ -1653,18 +1713,21 @@ int mangle(int fd, char *buffer) {
    */
    */
 
 
   if (need_render) {
   if (need_render) {
-    ZF_LOGD("HH %d : (%d) %s", need_render, (int)strlen(buffer), repr(buffer));
+    ZF_LOGD_MEM(play, len, "Ready to render:");
+    // ZF_LOGD("HH %d : (%d) %s", need_render, (int)strlen(buffer), repr(buffer));
   } else {
   } else {
     if (mangled) {
     if (mangled) {
-      ZF_LOGD("Mangled %d words, %d chars : %s", mangled, mangled_chars,
-              repr(buffer));
+      ZF_LOGD_MEM(play, len, "Mangled %d words, %d chars:", mangled,
+                  mangled_chars);
+      /* ZF_LOGD("Mangled %d words, %d chars : %s", mangled, mangled_chars,
+              repr(buffer)); */
     }
     }
   }
   }
 
 
   if (need_render) {
   if (need_render) {
-    render(fd, buffer);
+    render(fd, play, len);
   } else {
   } else {
-    write(fd, buffer, strlen(buffer));
+    write(fd, play, len); // strlen(buffer));
   };
   };
   return need_render && mangled;
   return need_render && mangled;
 }
 }
@@ -1686,7 +1749,7 @@ int harry_happens(time_t *last_event, int wakeup) {
 TO FIX:  Stop using c strings, must use char * buffer + int length.
 TO FIX:  Stop using c strings, must use char * buffer + int length.
 MAY CONTAIN NULL VALUES.
 MAY CONTAIN NULL VALUES.
 
 
-Rework some things here.  
+Rework some things here.
 
 
 Here's the "plan":
 Here's the "plan":
 
 
@@ -1705,10 +1768,11 @@ Here's the "plan":
 
 
   ON READ:
   ON READ:
     read/append to current buffer.
     read/append to current buffer.
-    We can't use nulls -- what if they are using ZModem, there's nulls in the file!
-    Look for trailing  / the very last "\r\n".  
+    We can't use nulls -- what if they are using ZModem, there's nulls in the
+file! Look for trailing  / the very last "\r\n".
 
 
-    (I could mangle/chunk it line by line.  But I'm not sure I'd need to do that.)
+    (I could mangle/chunk it line by line.  But I'm not sure I'd need to do
+that.)
 
 
     Optional "mangle" buffer up to that very point -- and send up to that point.
     Optional "mangle" buffer up to that very point -- and send up to that point.
 
 
@@ -1722,14 +1786,59 @@ Here's the "plan":
     else:
     else:
       Ok, we *STILL* haven't received any more characters into the buffer --
       Ok, we *STILL* haven't received any more characters into the buffer --
       even after waiting.  (Maybe we haven't waited long enough?)
       even after waiting.  (Maybe we haven't waited long enough?)
-      send the pending information in the buffer and clear it out. 
+      send the pending information in the buffer and clear it out.
       Maybe this is a prompt, and there won't be a \r\n.
       Maybe this is a prompt, and there won't be a \r\n.
 
 
 This allows for cleaner process of "lines" of buffer.  We shouldn't break
 This allows for cleaner process of "lines" of buffer.  We shouldn't break
 in the midDLE OF A WORD.  Downside is that we sit on buffer contents a little
 in the midDLE OF A WORD.  Downside is that we sit on buffer contents a little
 while / some amount of time -- which will add some lag to prompts showing up.
 while / some amount of time -- which will add some lag to prompts showing up.
 
 
+
+ZModem:
+
+    start:  "rz^M**"...
+
+    05-12 18:12:15.916 >> rz^M**^XB00000000000000^M<8A>^Q
+    05-12 18:12:15.928 << **\x18B0100000023be50\r\n\x11
+    05-12 18:12:15.928 >> *^XC^D
+    05-12 18:12:15.939 << **\x18B0900000000a87c\r\n\x11
+    05-12 18:12:15.940 >> *^XC
+    # Start of PK zipfile.
+    05-12 18:12:15.941 >> PK^C^D^T
+
+    end:
+    05-12 18:26:38.700 << **\x18B0100000023be50\r\n\x11
+    05-12 18:26:38.700 >> **^XB0823a77600344c^M<8A>
+    05-12 18:26:38.711 << **\x18B0800000000022d\r\n
+    05-12 18:26:38.712 >> OO^MESC[0m
+
+ */
+
+/*
+ * rstrnstr() Reverse string find in a string
+ *
+ * This obeys the len, and handles nulls in buffer.
+ * find is a c-string (null terminated)
  */
  */
+int rstrnstr(const char *buffer, int len, const char *find) {
+  int flen = strlen(find);
+
+  if (len < flen) {
+    // I can't find a string in a buffer smaller then it is!
+    return -1;
+  }
+  int pos = len - flen;
+  while (pos > 0) {
+    if (buffer[pos] == find[0]) {
+      // First chars match, check them all.
+      if (strncmp(buffer + pos, find, flen) == 0) {
+        return pos;
+      }
+    }
+    pos--;
+  }
+  return -1;
+}
 
 
 int main(int argc, char *argv[]) {
 int main(int argc, char *argv[]) {
   int master;
   int master;
@@ -1781,9 +1890,6 @@ int main(int argc, char *argv[]) {
   if (!init_regex())
   if (!init_regex())
     return 2;
     return 2;
 
 
-  // With IGNBRK  I don't think I need this anymore.  (Nope!)
-  // signal(SIGINT, SIG_IGN);
-
   pid = forkpty(&master, NULL, NULL, NULL);
   pid = forkpty(&master, NULL, NULL, NULL);
 
 
   // impossible to fork
   // impossible to fork
@@ -1808,8 +1914,6 @@ int main(int argc, char *argv[]) {
 
 
   // parent
   // parent
   else {
   else {
-    // remove the echo
-    // ICANON - raw mode.  No more line buffering!
     struct termios tios, orig1;
     struct termios tios, orig1;
     struct timeval timeout;
     struct timeval timeout;
     time_t last_event = 0; // time(NULL);
     time_t last_event = 0; // time(NULL);
@@ -1818,19 +1922,27 @@ int main(int argc, char *argv[]) {
 
 
     tcgetattr(master, &tios);
     tcgetattr(master, &tios);
     tios.c_lflag &= ~(ECHO | ECHONL | ICANON);
     tios.c_lflag &= ~(ECHO | ECHONL | ICANON);
+    /*
+    tios.c_iflag &= ~(ICRNL | IXON | BRKINT);
+    tios.c_iflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
+    tios.c_oflag &= ~(OPOST);
+    */
     tcsetattr(master, TCSAFLUSH, &tios);
     tcsetattr(master, TCSAFLUSH, &tios);
 
 
     tcgetattr(1, &orig1);
     tcgetattr(1, &orig1);
     tios = orig1;
     tios = orig1;
-    tios.c_iflag &= ~(ICRNL | IXON); // Disable software flow control
-
+    tios.c_iflag &= ~(ICRNL | IXON | BRKINT);
     tios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
     tios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
+    tios.c_oflag &= ~(OPOST);
 
 
     // https://viewsourcecode.org/snaptoken/kilo/02.enteringRawMode.html
     // https://viewsourcecode.org/snaptoken/kilo/02.enteringRawMode.html
-    // ISIG should be Ctrl-C and Ctrl-Z IGNBRK +
     tcsetattr(1, TCSAFLUSH, &tios);
     tcsetattr(1, TCSAFLUSH, &tios);
 
 
+    char buffer[1024];
+    int size = 0;
+
     for (;;) {
     for (;;) {
+      int time_idle;
 
 
       // define estruturas para o select, que serve para verificar qual
       // define estruturas para o select, que serve para verificar qual
       // se tornou "pronto pra uso"
       // se tornou "pronto pra uso"
@@ -1858,67 +1970,117 @@ int main(int argc, char *argv[]) {
        And as we get closer, 15-25 seconds.
        And as we get closer, 15-25 seconds.
       */
       */
 
 
-      // we're in luck!  The last parameter is time interval/timeout.  :D
-      timeout.tv_sec = 10;
-      timeout.tv_usec = 0;
+      if (size == 0) {
+        // buffer is empty
+        timeout.tv_sec = randrange(10, 20);
+        timeout.tv_usec = 0;
+        time_idle = 1;
+      } else {
+        // buffer is not empty
+        timeout.tv_sec = 0;
+        timeout.tv_usec = 1;
+        time_idle = 0;
+      }
 
 
-      // select(master+1, &read_fd, &write_fd, &except_fd, NULL);
       if (select(master + 1, &read_fd, &write_fd, &except_fd, &timeout) == 0) {
       if (select(master + 1, &read_fd, &write_fd, &except_fd, &timeout) == 0) {
         // This means timeout!
         // This means timeout!
-        ZF_LOGI("TIMEOUT");
-        harry_idle_event(STDOUT_FILENO);
+        if (time_idle) {
+          ZF_LOGI("TIMEOUT");
+          harry_idle_event(STDOUT_FILENO);
+        } else {
+          ZF_LOGI_MEM(buffer, size, "TIMEOUT size=%d", size);
+          console_receive(&console, buffer, size);
+          write(STDOUT_FILENO, buffer, size);
+          size = 0;
+          // buffer is empty now
+        }
       }
       }
 
 
-      char input[BSIZE + 1];
+      /*
       static char output[(BSIZE * 4) + 1];
       static char output[(BSIZE * 4) + 1];
+      */
       int total;
       int total;
 
 
       // read_fd esta atribuido com read_fd?
       // read_fd esta atribuido com read_fd?
       if (FD_ISSET(master, &read_fd)) {
       if (FD_ISSET(master, &read_fd)) {
         // leia o que bc esta mandando
         // leia o que bc esta mandando
-        if ((total = read(master, &output, BSIZE)) != -1) {
-          // e escreva isso na saida padrao
-          output[total] = 0;
-
-          // if ( harry_happens( &last_event, 5)) {
-          if (1) {
-            ZF_LOGI("harry_happens");
-            if (mangle(STDOUT_FILENO, output) == 0) {
-              // failed, so.  Try again.
-              last_event = 0;
-            }
+        // ZF_LOGD("read (%d) %d bytes", size, BSIZE - size);
+
+        if ((total = read(master, buffer + size, BSIZE - size)) != -1) {
+          // Ok, we've read more into the buffer.
+          // ZF_LOGD("total = %d", total);
+          /*
+          // this ... isn't working.
+          ZF_LOGD_MEM(buffer, total, "Buffer now:");
+          write(STDOUT_FILENO, buffer, total);
+          size = 0;
+          */
+
+          ZF_LOGD_MEM(buffer + size, total, "Read %d bytes:", total);
+          size += total;
+          ZF_LOGD_MEM(buffer, size, "Buffer now:");
+          int pos = rstrnstr(buffer, size, "\r\n");
+          if (pos >= 0) {
+            // found something!
+            pos += 2;
+            ZF_LOGD_MEM(buffer, pos, "mangle buffer %d bytes:", pos);
+            mangle(STDOUT_FILENO, buffer, pos);
+            memmove(buffer, buffer + pos, size - pos);
+            size -= pos;
           } else {
           } else {
-            write(STDOUT_FILENO, &output, total);
-            // This is OUTPUT from the BBS
-            // ZF_LOGI( ">> %s", repr(output));
-            ZF_LOGI(">> %d chars", (int)strlen(output));
-            //   I think repr is flipping out here.  :(
-            // ZF_LOGI( ">> %d", (int)strlen(repr(output)));
+            ZF_LOGD("position of /r/n not found.");
           }
           }
 
 
         } else
         } else
           break;
           break;
       }
       }
 
 
-      // read_fd esta atribuido com a entrada padrao?
-      if (FD_ISSET(STDIN_FILENO, &read_fd)) {
-        // leia a entrada padrao
-        total = read(STDIN_FILENO, &input, BSIZE);
-        input[total] = 0;
-        // e escreva no bc
-        ZF_LOGI("<< %s", repr(input));
-
-        write(master, &input, total);
+#ifdef OLD_CRUFTY
+      if ((total = read(master, &output, BSIZE)) != -1) {
+        // e escreva isso na saida padrao
+        output[total] = 0;
+
+        // if ( harry_happens( &last_event, 5)) {
+        if (1) {
+          ZF_LOGI("harry_happens");
+          if (mangle(STDOUT_FILENO, output) == 0) {
+            // failed, so.  Try again.
+            last_event = 0;
+          }
+        } else {
+          write(STDOUT_FILENO, &output, total);
+          // This is OUTPUT from the BBS
+          // ZF_LOGI( ">> %s", repr(output));
+          ZF_LOGI(">> %d chars", (int)strlen(output));
+          //   I think repr is flipping out here.  :(
+          // ZF_LOGI( ">> %d", (int)strlen(repr(output)));
+        }
 
 
-        // This is INPUT from the USER
-        // ZF_LOGI_MEM( input, strlen(input), "<< ");
-      }
+      } else
+        break;
     }
     }
+#endif
+
+    // read_fd esta atribuido com a entrada padrao?
+    if (FD_ISSET(STDIN_FILENO, &read_fd)) {
+      // leia a entrada padrao
+      char input[BSIZE];
+      int r = read(STDIN_FILENO, &input, BSIZE);
+      input[r] = 0;
+      // e escreva no bc
+      ZF_LOGI("<< %s", repr(input));
+
+      write(master, &input, r);
 
 
-    // Restore terminal
-    tcsetattr(1, TCSAFLUSH, &orig1);
-    ZF_LOGD("exit");
+      // This is INPUT from the USER
+      // ZF_LOGI_MEM( input, strlen(input), "<< ");
+    }
   }
   }
 
 
-  return 0;
+  // Restore terminal
+  tcsetattr(1, TCSAFLUSH, &orig1);
+  ZF_LOGD("exit");
+}
+
+return 0;
 }
 }