--- /dev/null
+#define _GNU_SOURCE 1
+#include <dlfcn.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+static int (*fputs2) (const char *s, FILE *stream) = NULL;
+static size_t (*fwrite2) (const void *ptr, size_t size, size_t nmemb,
+ FILE *stream);
+static int is_gdb;
+
+static void __attribute__((constructor))
+init (void)
+{
+ if (getenv ("WRITEW_IS_GDB"))
+ {
+ /* GDB */
+ unsetenv ("LD_PRELOAD");
+ is_gdb = 1;
+ }
+ else
+ {
+ /* expect */
+ setenv ("WRITEW_IS_GDB", "1", 1);
+ }
+ fputs2 = dlsym (RTLD_NEXT, "fputs");
+ assert (fputs2 != NULL);
+ fwrite2 = dlsym (RTLD_NEXT, "fwrite");
+ assert (fwrite2 != NULL);
+}
+
+static int
+pid_is_sleeping (pid_t pid)
+{
+ FILE *status_file;
+ char buf[100];
+ int retval = 0;
+
+ snprintf (buf, sizeof (buf), "/proc/%d/status", (int) pid);
+ status_file = fopen (buf, "r");
+ if (status_file != NULL)
+ {
+ int have_state = 0;
+
+ while (fgets (buf, sizeof (buf), status_file))
+ {
+ if (strncmp (buf, "State:", 6) == 0)
+ {
+ have_state = 1;
+ break;
+ }
+ }
+ if (have_state && strstr (buf, "S (sleeping)") != NULL)
+ retval = 1;
+ fclose (status_file);
+ }
+ return retval;
+}
+
+static void
+delay (void)
+{
+ pid_t expect_pid = getppid ();
+
+ do
+ usleep (1000 * 1000 / 100);
+ while (!pid_is_sleeping (expect_pid));
+}
+
+int
+fputs (const char *s, FILE *stream)
+{
+ int retval = fputs2 (s, stream);
+
+ if (is_gdb && fileno (stream) == STDOUT_FILENO && strchr (s, '\n'))
+ delay ();
+
+ return retval;
+}
+
+size_t
+fwrite (const void *ptr, size_t size, size_t nmemb, FILE *stream)
+{
+ size_t retval = fwrite2 (ptr, size, nmemb, stream);
+
+ if (is_gdb && fileno (stream) == STDOUT_FILENO
+ && memchr (ptr, '\n', size * nmemb))
+ delay ();
+
+ return retval;
+}