Ok, here's the patch to add the %s{script} form
to log-file expansion.  The script is run via
/bin/bash -c script, and its output replaces the
while %s form.  The max length my code allows
for the result is 500 characters, which seemed
enough for anything realistic.  Note that the
pid of the invoking valgrind will be the script's
PPID, etc.

If the "powers that be" think this might be
generally useful, then let me know how you would
prefer to receive the patch, and any tidying you
feel would be in order ...

Regards -- Eliot Moss
Index: m_options.c
===================================================================
--- m_options.c (revision 12572)
+++ m_options.c (working copy)
@@ -227,6 +227,122 @@
                goto bad;
             }
          } 
+         else if ('s' == format[i]) {
+            i++;
+            if ('{' == format[i]) {
+               // Get the script name, get organized to invoke it
+               Char* scriptname;
+               Char* result;
+               i++;
+               scriptname = &format[i];
+               while (True) {
+                  if (0 == format[i]) {
+                     VG_(fmsg)("%s: malformed %%s specifier\n", option_name);
+                     goto bad;
+                  } else if ('}' == format[i]) {
+                     // Temporarily replace the '}' with NUL to extract script
+                     // name.
+                     format[i] = 0;
+                    Char *tempBuf = VG_(malloc)( "options.efn.3", 
VG_(strlen)(scriptname) );
+                    VG_(strcpy)( tempBuf, scriptname );
+                    scriptname = tempBuf;
+                    format[i] = '}';
+
+                    Int fd[2];
+                    Int err;
+                    if ( (err = VG_(pipe)(fd)) < 0) {
+                       VG_(fmsg)("%s: could not create pipe for script; 
err=%d\n", option_name, err);
+                       goto bad;
+                    }
+
+                    Int pid = VG_(fork)();
+                    if (pid < 0) {
+                       // could not fork to execute script -- die!
+                       VG_(fmsg)("%s: could not fork to run script; err=%d\n", 
option_name, pid);
+                       VG_(close)(fd[0]);
+                       VG_(close)(fd[1]);
+                       goto bad;
+                    }
+
+                    if (pid == 0) { // child
+                       VG_(close)(fd[0]);   // don't need the input side of 
the pipe
+                       VG_(close)(1);       // want to replace standard output
+                       VG_(dup2)(fd[1], 1); // now have pipe for output
+                       VG_(close)(fd[1]);   // close old fd
+                       Char* argv[4] = { "/bin/sh", "-c", scriptname, 0 };
+                       VG_(execv)(argv[0], argv);
+                       VG_(exit)(1);  // should not get here!
+                    }
+
+                    VG_(close)(fd[1]);
+                    Int incr = 100;
+                    Int max = incr;
+                    Int hardmax = 5 * incr;
+                    Char* buf = VG_(malloc)( "options.efn.4", max+1 );
+                    Int idx = 0;
+                    Int amt;
+                    while ( (amt = VG_(read)( fd[0], buf+idx, max-idx )) > 0 ) 
{
+                       Int lim = idx + amt;
+                       while ( idx < lim ) {
+                          if (buf[idx] == '\n' || buf[idx] == 0) {
+                             break;
+                          }
+                          idx++;
+                       }
+                       if (idx < lim) {
+                          break;
+                       }
+                       if ( idx == max ) {
+                          if ( max >= hardmax ) {
+                             VG_(fmsg)("%s script output too large; 
truncating\n", scriptname);
+                             amt = 0;
+                             break;
+                          }
+                          max += incr;
+                          buf = VG_(realloc)( "options.efn.5", buf, max+1 );
+                       }
+                    }
+                    if ( amt < 0 ) {
+                       VG_(fmsg)("%s script: error reading output; err=%d\n", 
scriptname, amt);
+                       goto bad;
+                    }
+                    buf[idx] = 0;
+                    VG_(close)(fd[0]);
+                     i++;  // over the }
+                    result = buf;
+
+                    { // code cribbed from m_libcproc.c: system
+                      // wait for child to finish
+                      Int ir, zzz;
+                      vki_sigaction_toK_t sa, sa2;
+                      vki_sigaction_fromK_t saved_sa;
+                      VG_(memset)( &sa, 0, sizeof(sa) );
+                      VG_(sigemptyset)(&sa.sa_mask);
+                      sa.ksa_handler = VKI_SIG_DFL;
+                      sa.sa_flags    = 0;
+                      ir = VG_(sigaction)(VKI_SIGCHLD, &sa, &saved_sa);
+                      vg_assert(ir == 0);
+
+                      zzz = VG_(waitpid)(pid, NULL, 0);
+
+                      VG_(convert_sigaction_fromK_to_toK)( &saved_sa, &sa2 );
+                      ir = VG_(sigaction)(VKI_SIGCHLD, &sa2, NULL);
+                      vg_assert(ir == 0);
+                      if (zzz < 0) {
+                        VG_(fmsg)("%s: script returned code %d\n", scriptname, 
zzz);
+                      }
+                    }
+                     break;
+                  }
+                  i++;
+               }
+               ENSURE_THIS_MUCH_SPACE(VG_(strlen)(result));
+               j += VG_(sprintf)(&out[j], "%s", result);
+            } else {
+               VG_(fmsg)("%s: expected '{' after '%%s'\n", option_name);
+               goto bad;
+            }
+         }
          else {
             // Something else, abort.
             VG_(fmsg)("%s: expected 'p' or 'q' or '%%' after '%%'\n",
@@ -242,7 +358,7 @@
 
   bad: {
    Char* opt =    // 2:  1 for the '=', 1 for the NUL.
-      VG_(malloc)( "options.efn.3",
+      VG_(malloc)( "options.efn.6",
                    VG_(strlen)(option_name) + VG_(strlen)(format) + 2 );
    VG_(strcpy)(opt, option_name);
    VG_(strcat)(opt, "=");
------------------------------------------------------------------------------
Meet PCI DSS 3.0 Compliance Requirements with EventLog Analyzer
Achieve PCI DSS 3.0 Compliant Status with Out-of-the-box PCI DSS Reports
Are you Audit-Ready for PCI DSS 3.0 Compliance? Download White paper
Comply to PCI DSS 3.0 Requirement 10 and 11.5 with EventLog Analyzer
http://pubads.g.doubleclick.net/gampad/clk?id=154622311&iu=/4140/ostg.clktrk
_______________________________________________
Valgrind-users mailing list
Valgrind-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/valgrind-users

Reply via email to