Implement logging to a network socket.  So it's now possible to do
valgrind ... --logsocket=192.168.0.1:1500 or whatever, to send all
output to that address/port combination.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1272 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/vg_main.c b/coregrind/vg_main.c
index d26bc29..30fcac7 100644
--- a/coregrind/vg_main.c
+++ b/coregrind/vg_main.c
@@ -284,7 +284,7 @@
 
    VGOFF_(helper_CLC)
       = alloc_BaB_1_set( (Addr) & VG_(helper_CLC) );
-    VGOFF_(helper_STC)
+   VGOFF_(helper_STC)
       = alloc_BaB_1_set( (Addr) & VG_(helper_STC) );
 
    VGOFF_(helper_shldl)
@@ -383,6 +383,10 @@
    real. */
 UInt VG_(exitcode) = 0;
 
+/* Tell the logging mechanism whether we are logging to a file
+   descriptor or a socket descriptor. */
+Bool VG_(logging_to_filedes) = True;
+
 
 /* ---------------------------------------------------------------------
    Counters, for informational purposes only.
@@ -637,6 +641,7 @@
 "    --run-libc-freeres=no|yes Free up glibc memory at exit? [yes]\n"
 "    --logfile-fd=<number>     file descriptor for messages [2=stderr]\n"
 "    --logfile=<file>          log messages to <file>.pid<pid>\n"
+"    --logsocket=ipaddr:port   log messages to socket ipaddr:port\n"
 "    --suppressions=<filename> suppress errors described in\n"
 "                              suppressions file <filename>\n"
 "    --weird-hacks=hack1,hack2,...  [no hacks selected]\n"
@@ -907,6 +912,11 @@
          VG_(clo_logfile_name) = &argv[i][10];
       }
 
+      else if (STREQN(12, argv[i], "--logsocket=")) {
+         VG_(clo_log_to)       = VgLogTo_Socket;
+         VG_(clo_logfile_name) = &argv[i][12];
+      }
+
       else if (STREQN(15, argv[i], "--suppressions=")) {
          if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
             VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
@@ -1047,15 +1057,15 @@
       the terminal any problems to do with processing command line
       opts. */
    vg_assert(VG_(clo_logfile_fd) == 2 /* stderr */);
+   vg_assert(VG_(logging_to_filedes) == True);
 
    switch (VG_(clo_log_to)) {
-      case VgLogTo_Socket: 
-         VG_(core_panic)("VgLogTo_Socket ?!"); 
-         break;
+
       case VgLogTo_Fd: 
          vg_assert(VG_(clo_logfile_name) == NULL);
          VG_(clo_logfile_fd) = eventually_logfile_fd;
          break;
+
       case VgLogTo_File: {
          Char logfilename[1000];
          vg_assert(VG_(clo_logfile_name) != NULL);
@@ -1075,7 +1085,34 @@
                "--logfile=<file> didn't work out for some reason.");
          }
          break;
+      }
+
+      case VgLogTo_Socket: {
+         vg_assert(VG_(clo_logfile_name) != NULL);
+         vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
+         eventually_logfile_fd 
+            = VG_(connect_via_socket)( VG_(clo_logfile_name) );
+         if (eventually_logfile_fd == -1) {
+            VG_(message)(Vg_UserMsg, 
+               "Invalid --logsocket=ipaddr or --logsocket=ipaddr:port spec"); 
+            VG_(message)(Vg_UserMsg, 
+               "of `%s'; giving up!", VG_(clo_logfile_name) );
+            VG_(bad_option)(
+               "--logsocket=");
 	 }
+         if (eventually_logfile_fd == -2) {
+            VG_(message)(Vg_UserMsg, 
+               "Failed to connect to logging server `%s'; giving up",
+               VG_(clo_logfile_name) ); 
+            VG_(bad_option)(
+               "--logsocket= (timeout during connect)");
+	 }
+	 vg_assert(eventually_logfile_fd > 0);
+         VG_(clo_logfile_fd) = eventually_logfile_fd;
+         VG_(logging_to_filedes) = False;
+         break;
+      }
+
    }
 
    /* Ok, the logging sink is running now.  Print a suitable preamble.