pio.h source code

#ifndef __PIO_H__
#define __PIO_H__


FILE* popen(const char* shell_cmd, const char* mode);

int pclose(FILE* fstream);

#endif

pio.c source code

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>
#include <limits.h>
#include "pio.h"

static int num_sh = 0;

struct sh_rec
{
   pid_t	sh_pid; 
   FILE*	stream;
}  sh_info[OPEN_MAX];

FILE *popen(const char *shell_cmd, const char *mode)
{
   int fifo[2];
   if ((strcmp(mode , "r") && strcmp(mode, "w")) || pipe(fifo) == -1)
      return 0;
      
   switch (sh_info[num_sh].sh_pid = fork())
   {
      case -1:	perror("fork"); return 0;
      case 0:	(*mode == 'r') ? dup2(fifo[1], STDOUT_FILENO) :
                            	 dup2(fifo[0], STDIN_FILENO);
                close(fifo[0]);
                close(fifo[1]);      
                execl("/bin/sh", "sh", "-c", shell_cmd, 0);
                exit(5);
   }
   if (*mode == 'r')
   {
      close(fifo[1]);
      return (sh_info[num_sh++].stream = fdopen(fifo[0], mode));
   }
   else
    {
      close(fifo[0]);
      return (sh_info[num_sh++].stream = fdopen(fifo[1], mode));
   }
}   

int pclose(FILE *fstream)
{
   int i, status, rc = -1;
   
   for (i = 0; i < num_sh; i++)
      if (sh_info[i].stream == fstream)
         break;
         
   if (i == num_sh) return -1;
   
   close(fstream);
   
   if (waitpid(sh_info[i].sh_pid, &status, 0) == sh_info[i].sh_pid || WIFEXITED(status))
      rc = WEXITSTATUS(status);
      
   for (i++; i < num_sh; i++)
      sh_info[i-1] = sh_info[i];
      
   num_sh--;
   
   return rc;
}