title: monitor bytes in stdin, stdout, and stderr in C
body: <p>I need to count how many bytes are being sent to a child process through stdin, and how many bytes a child process is writing to stdout and stderr. The child process calls execvp, so I have no way to monitor those stats from within the process itself. My current tactic involves creating 3 additional child processes, one each to monitor each of the std streams through pipes (or in the case of stdin, just reading from stdin). </p>
  
  <p>This tactic seems really frail at best, and I'm doing something strange which makes it so that the processes monitoring stdout/err cannot read from their respective ends of the pipes (and makes them hang indefinitely). Code below.</p>
  
  <p>This creates the three helper child processes, and should allow them to count the stats: </p>
  
  <pre><code>void controles(struct fds *des)
  {
      int ex[2];
      int err[2];
  
      int n_in = 0;
      int c_in;
  
      int n_ex = 0;
      int c_ex;
  
      int n_err = 0;
      int c_err;
  
      pipe(ex);
      pipe(err);
  
      /*has two fields, for the write end of the stdout pipe and the stderr pipe. */
      des-&gt;err = err[1];
      des-&gt;ex = ex[1];
      switch (fork()) {
      case 0:     /*stdin */
          while (read(0, &amp;c_in, 1) == 1)
              n_in++;
          if (n_in &gt; 0)
              printf("%d bytes to stdin\n", n_in);
          exit(n_in);
      default:
          break;
      }
  
      switch (fork()) {
      case 0:     /*stdout */
          close(ex[1]);
          /*pretty sure this is wrong */
          while (read(ex[0], &amp;c_ex, 1) == 1) {
              n_ex++;
              write(1, &amp;c_ex, 1);
          }
          if (n_ex &gt; 0)
              printf("%d bytes to stdout\n", n_ex);
          close(ex[0]);
          exit(n_ex);
      default:
          close(ex[0]);
      }
      switch (fork()) {
      case 0:     /*error */
          close(err[1]);
          /*also probably have a problem here */
          while (read(err[0], &amp;c_err, 1) == 1) {
              n_err++;
              write(2, &amp;c_err, 1);
          }
          if (n_err &gt; 0)
              printf("%d bytes to stderr\n", n_err);
          close(err[0]);
          exit(n_err);
      default:
          close(err[0]);
      }
  }
  </code></pre>
  
  <p>and this is a code fragment (within the child process) which sets up the two fd's from the fds struct so that the child process should write to the pipe instead of stdin/stderr.</p>
  
  <pre><code>    dup2(des.ex, 1);
  dup2(des.err, 2);
  close(des.ex); close(des.err); /*Is this right?*/
  execvp(opts-&gt;exec, opts-&gt;options); /*sure this is working fine*/
  </code></pre>
  
  <p>I'm lost, any help would be appreciated.</p>