

static char *rcsid = "filtered-fp.c";



#include <unistd.h>


#include "filtered-fp.h"

int trynew = 0;                              /* testing */



FILE *filtered_fp(FILE *fp, char *cmd, char **args)
{
  return filtered_fp_putchars(fp, cmd, args, NULL, 0);
}


FILE *filtered_fp_putchars(FILE *fp, char *cmd, char **args, int *chrs, int nchrs)
{
  int i, ch;
  int pid1, pid2;
  int pipefds[2], write1fd, read1fd, write2fd, read2fd, stdinfd, stdoutfd;
  int fpfd;
  int fromstdin;
  
  
  if (fp == (FILE *) NULL) {
    return (FILE *) NULL;
  }

  fpfd = fileno(fp);

  fromstdin = (fp == stdin);

  pipe(pipefds);
  read1fd  = pipefds[0];
  write1fd = pipefds[1];  

  if ((pid1 = fork()) == 0) {
    FILE *tfp;
    
    close(read1fd);
    tfp = fdopen(write1fd, "w");

    for (i = 0; i < nchrs; i++) {
      putc(chrs[i], tfp);
    }
    
    while ((ch = getc(fp)) != EOF) {
      putc(ch, tfp);
    }

    fclose(fp);
    fclose(tfp);
    _exit(0);
  }
  else {
    close(write1fd);
    
    pipe(pipefds);
    read2fd  = pipefds[0];
    write2fd = pipefds[1];  

    stdinfd  = fileno(stdin);
    stdoutfd = fileno(stdout);
  
    if ((pid2 = fork()) == 0) {
      close(read2fd);
      dup2(read1fd, stdinfd);
      dup2(write2fd, stdoutfd);
      close(read1fd);
      close(write2fd);
      if (execv(cmd, args)) {
        panicfv("execv() returned in filtered_fp_putchars()", _exit, 1);
      }
    }
    else {
      close(read1fd);
      close(write2fd);

      if (trynew) {
        /* really want something like an fdreopen() to overlay the original file pointer */
        /* */
#if      0
        dup2(read2fd, fpfd);
        fp->_cnt = 0;                        /* set buffer empty */
      
        close(read2fd);
#endif  

        FILE *ffp, tmp;
        ffp = fdopen(read2fd, "r");
        tmp = *ffp;
        *ffp = *fp;
        *fp = tmp;
        fclose(ffp);
        
        return fp;
      } else {
        FILE *ffp;

        fclose(fp);
        ffp = fdopen(read2fd, "r");
        if (fromstdin) {
          dup2(read2fd, stdinfd);
        }
        return ffp;
      }
    }
  }

  return NULL;                               /* make gcc not complain */
}




