V10/cmd/library/dospopen.c

/*	library:dospopen.c	1.2	*/
#include "sccsid.h"
VERSION(@(#)library:dospopen.c	1.2)

/* popen/pclose: simple MS-DOS piping scheme to imitate UNIX pipes */

/* information needed between popen and pclose */
#include <stdio.h>

static char *prgname[32];          /* program name if write pipe */
static int pipetype[32];           /* 1=read 2=write */

/* open a pipe */
FILE *popen(prg,type)
char *prg,*type;
{ FILE *p;
  int ostdout, ostdin;

  switch(*type) {

    /* for write style pipe, pclose handles program execution */
    case 'w' :
      if ((p= fopen("\\pipe.tmp","w")) != NULL) {
        pipetype[fileno(p)]= 1;
        prgname[fileno(p)]= prg;
      }
      return(p);

/* read pipe must create tmp file, set up stdout to point to the temp
 * file, and run the program.  note that if the pipe file cannot be
 * opened, it'll return a condition indicating pipe failure, which is
 * fine.
 */

    case 'r' :
      if ((p= fopen("\\pipe.tmp","w")) != NULL) {
        pipetype[fileno(p)]= 2;
        ostdout= dup(fileno(stdout));   /* we need this later */
        dup2(fileno(stdout),fileno(p)); /* substitute for stdout */
        system(prg);                    /* run the program */
        dup2(fileno(stdout),ostdout);   /* repair stdout */
        fclose(p);                      /* close redirected stdout */
        return(fopen("\\pipe.tmp","r"));     /* return pointer to tmp file */
      }
      return(NULL);                     /* everyone has their problems */

    /* screwy call or unsupported type */
    default :
      printf("popen: unknown pipe style\n");
      exit(1);
  }
}

/* close a pipe */
void pclose(p)
FILE *p;
{ int n;
  int ostdout, ostdin;
  FILE *p2;

  switch(pipetype[fileno(p)]) {

/* close the temp file, open again as read, redirect stdin from that
 * file, run the program, then clean up.
 */

    case 1 :
      n= fileno(p);
      fclose(p);
      if ((p2= fopen("\\pipe.tmp","r")) != NULL) {
        ostdin= dup(fileno(stdin));     /* save stdin for later */
        dup2(fileno(stdin),fileno(p2)); /* redirect to tmp file */
        system(prgname[n]);             /* run the program */
        dup2(fileno(stdin),ostdin);     /* repair stdin */
        fclose(p2);
        unlink("\\pipe.tmp");            /* erase tmp file */
        return;
      }
      printf("pclose: could not reopen temporary file\n");
      exit(1);

    /* close the temp file and remove it */
    case 2 :
      n= fileno(p);        /* get file number for unlink */
      fclose(p);           /* close the file */
      unlink("\\pipe.tmp"); /* erase the file */
      return;

    /* if we're neither read nor write, we have problems */
    default :
      printf("pclose: internal error\n");
      exit(1);
  }
}