#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/select.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#endif
}
+static int wait_for_write(int fd, int timeout) {
+ fd_set rfds;
+ struct timeval tv;
+ int result;
+
+ FD_ZERO(&rfds);
+ FD_SET(fd, &rfds);
+
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+
+ result = select(fd + 1, &rfds, NULL, NULL, &tv);
+ if (result < 0) {
+ perror("select");
+ return 0;
+ }
+ if (result == 0) {
+ /* Timeout. */
+ return 0;
+ }
+
+ /* Got more data to read. */
+ return 1;
+}
+
static void pass_buffer_to_program(const char *buffer, size_t length, char **argv) {
int fds[2];
FILE *fh;
char buffer[4096];
ssize_t r;
+ assert(SSIZE_MAX <= SIZE_MAX);
while ((r = read(fd, buffer, sizeof(buffer))) > 0) {
- assert(SSIZE_MAX <= SIZE_MAX);
+ size_t space;
+ ssize_t r2;
+
+ /* To prevent partial messages (sometimes it takes multiple reads to
+ * get the complete message) wait for a short time to get the rest of
+ * the message. */
+ space = sizeof(buffer) - (size_t)r;
+ while (space > 0 && wait_for_write(fd, 1 /* second */)) {
+ r2 = read(fd, buffer + r, space);
+ if (r2 <= 0) {
+ break;
+ }
+ r += r2;
+ space -= (size_t)r2;
+ }
+
pass_buffer_to_program(buffer, (size_t)r, argv);
}
}