]> ruderich.org/simon Gitweb - wall-notify/wall-notify.git/commitdiff
retrieve the full message with select(2)
authorSimon Ruderich <simon@ruderich.org>
Sun, 11 May 2014 14:20:16 +0000 (16:20 +0200)
committerSimon Ruderich <simon@ruderich.org>
Sun, 11 May 2014 14:20:16 +0000 (16:20 +0200)
src/wall-notify.c

index c502bce0862e1c4a2379116b2cf3a6150be6361e..343f3d0ff37bfbb5a6798ee70158dbbed0cceb4a 100644 (file)
@@ -29,6 +29,7 @@
 #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>
@@ -161,6 +162,31 @@ static int logout(int ptm) {
 #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;
@@ -218,8 +244,24 @@ static void handle_wall(int fd, char **argv) {
     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);
     }
 }