Add a simple listener program, which captures output from --logsocket=.
Works, but needs refinement, + connection to the build system.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1275 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/auxprogs/valgrind-listener.c b/auxprogs/valgrind-listener.c
new file mode 100644
index 0000000..d7f8561
--- /dev/null
+++ b/auxprogs/valgrind-listener.c
@@ -0,0 +1,266 @@
+
+/*--------------------------------------------------------------------*/
+/*--- A simple program to listen for valgrind logfile data.        ---*/
+/*---                                          valgrind-listener.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+   This file is part of Valgrind, an extensible x86 protected-mode
+   emulator for monitoring program execution on x86-Unixes.
+
+   Copyright (C) 2000-2002 Julian Seward 
+      jseward@acm.org
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+
+/*---------------------------------------------------------------*/
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <unistd.h> /* close */
+#include <string.h>
+#include <assert.h>
+#include <sys/poll.h>
+#include <time.h>
+#include <fcntl.h>
+#include <stdlib.h>
+
+/*---------------------------------------------------------------*/
+
+#define SUCCESS 0
+#define ERROR   1
+
+#define END_LINE '\n'
+#define SERVER_PORT 1500
+#define MAX_CONNS 50
+
+/*---------------------------------------------------------------*/
+
+/* holds the fds for connections; zero if slot not in use. */
+int conn_count = 0;
+int           conn_fd[MAX_CONNS];
+struct pollfd conn_pollfd[MAX_CONNS];
+
+
+void set_nonblocking ( int sd )
+{
+   int res;
+   res = fcntl(sd, F_GETFL);
+   res = fcntl(sd, F_SETFL, res | O_NONBLOCK);
+   if (res != 0) {
+      perror("fcntl failed");
+      exit(ERROR);
+   }
+}
+
+void set_blocking ( int sd )
+{
+   int res;
+   res = fcntl(sd, F_GETFL);
+   res = fcntl(sd, F_SETFL, res & ~O_NONBLOCK);
+   if (res != 0) {
+      perror("fcntl failed");
+      exit(ERROR);
+   }
+}
+
+
+void copyout ( char* buf, int nbuf )
+{
+   int i;
+   for (i = 0; i < nbuf; i++) {
+     if (buf[i] == '\n') {
+       fprintf(stdout, "\n(%d) ", conn_count);
+     } else {
+       fwrite(&buf[i], 1, 1, stdout);
+     }
+   }
+}
+
+int read_from_sd ( int sd )
+{
+  char buf[100];
+  int n;
+
+  set_blocking(sd);
+  n = read(sd, buf, 99);
+  if (n <= 0) return 0; /* closed */
+  copyout(buf, n);
+
+  set_nonblocking(sd);
+  while (1) {
+     n = read(sd, buf, 100);
+     if (n <= 0) return 1; /* not closed */
+     copyout(buf, n);
+  }
+}
+
+
+void snooze ( void )
+{
+  struct timespec req;
+  req.tv_sec = 0;
+  req.tv_nsec = 200 * 1000 * 1000;
+  nanosleep(&req,NULL);
+}
+
+
+/* function readline */
+int read_line();
+
+int main (int argc, char *argv[]) {
+  int i, j, k, res;
+  int main_sd, newSd, cliLen;
+
+  struct sockaddr_in cliAddr, servAddr;
+
+  conn_count = 0;
+  for (i = 0; i < MAX_CONNS; i++)
+     conn_fd[i] = 0;
+
+  /* create socket */
+  main_sd = socket(AF_INET, SOCK_STREAM, 0);
+   if (main_sd < 0) {
+    perror("cannot open socket ");
+    return ERROR;
+  }
+  
+  /* bind server port */
+  servAddr.sin_family = AF_INET;
+  servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
+  servAddr.sin_port = htons(SERVER_PORT);
+  
+  if(bind(main_sd, (struct sockaddr *) &servAddr, sizeof(servAddr))<0) {
+    perror("cannot bind port ");
+    return ERROR;
+  }
+
+  res = listen(main_sd,MAX_CONNS);
+  if (res != 0) {
+    perror("listen failed ");
+    return ERROR;
+  }
+  
+  while(1) {
+
+    snooze();
+
+    /* enquire, using poll, whether there is any activity available on
+       the main socket descriptor.  If so, someone is trying to
+       connect; get the fd and add it to our table thereof. */
+    { struct pollfd ufd;
+      while (1) {
+         ufd.fd = main_sd;
+         ufd.events = POLLIN;
+         ufd.revents = 0;
+         res = poll(&ufd, 1, 0);
+         if (res == 0) break;
+
+	 /* ok, we have someone waiting to connect.  Get the sd. */
+         cliLen = sizeof(cliAddr);
+         newSd = accept(main_sd, (struct sockaddr *) &cliAddr, &cliLen);
+         if(newSd<0) {
+            perror("cannot accept connection ");
+            return ERROR;
+         }
+
+	 /* find a place to put it. */
+	 assert(newSd > 0);
+	 for (i = 0; i < MAX_CONNS; i++)
+            if (conn_fd[i] == 0) 
+               break;
+
+         if (i >= MAX_CONNS) {
+	   printf("too many concurrent connections\n");
+	   return ERROR;
+	 }
+         conn_fd[i] = newSd;
+	 conn_count++;
+	 printf("\n(%d) -------------------- CONNECT "
+                "--------------------\n(%d)\n(%d) ", 
+                conn_count, conn_count, conn_count);
+      }
+    }
+
+
+    /* We've processed all new connect requests.  Listen for changes
+       to the current set of fds. */
+    j = 0;
+    for (i = 0; i < MAX_CONNS; i++) {
+      if (conn_fd[i] == 0)
+	continue;
+      conn_pollfd[j].fd = conn_fd[i];
+      conn_pollfd[j].events = POLLIN | POLLHUP | POLLNVAL;
+      conn_pollfd[j].revents = 0;
+      j++;
+    }
+
+    res = poll(conn_pollfd, j, 0 /* return immediately. */ );
+
+    if (res < 0) {
+      perror("poll(main) failed");
+      return ERROR;
+    }
+    
+    /* nothing happened. go round again. */
+    if (res == 0) {
+       continue;
+    }
+
+    /* inspect the fds. */
+    for (i = 0; i < j; i++) {
+
+      if ((conn_pollfd[i].revents & POLLHUP) 
+          || (conn_pollfd[i].revents & POLLNVAL)) {
+	/* this fd has been closed or otherwise gone bad; forget about
+           it. */
+      closed:
+	for (k = 0; k < MAX_CONNS; k++)
+	  if (conn_fd[k] == conn_pollfd[i].fd) break;
+	assert(k < MAX_CONNS);
+	conn_fd[k] = 0;
+	 conn_count--;
+	printf("\n(%d) ------------------- DISCONNECT "
+               "-------------------\n(%d)\n(%d) ", 
+               conn_count, conn_count, conn_count);
+      }
+      else 
+      if (conn_pollfd[i].revents & POLLIN) {
+	/* data is available on this fd */
+	res = read_from_sd(conn_pollfd[i].fd);
+	if (res == 0) goto closed;
+      }
+
+    } /* for (i = 0; i < j; i++) */
+
+
+    
+  } /* while (1) */
+
+}
+
+
+/*--------------------------------------------------------------------*/
+/*--- end                                      valgrind-listener.c ---*/
+/*--------------------------------------------------------------------*/