
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/time.h>
#include<signal.h>
#include<sys/resource.h>
#include<sys/wait.h>
#include<errno.h>

#include<almemsys/almemsys.h>

// for pthread 
#include<pthread.h>

#include "sitar_com.h"

// for pthread 
// Pthreadに対応していますが、利用する関数側で以下を初期化してください。
// extern pthread_mutex_t popen_mutex;


// static int * pids[COM_LEN];
// extern int ** pids;


// static int *pids;

FILE * p_popen(FILE * iop, char * program, register char * type, int * pin, int *gin, int out, int count)
{
// static FILE * iop;
int pdes[2], pid, fdno;
char *argv[4];
int tes = 0;
argv[0] = "sh";
argv[1] = "-c";
argv[2] = (char *)program;
argv[3] = NULL;




//safe_pthread_mutex_lock(&popen_mutex);

//if(count < 0){
//   fprintf(stderr,"POPEN: p_open(): out of size pids[%d][x] %s\n", count, program );
//   return(NULL);
//   }

if((*type != 'r' && *type != 'w') || type[1]){
   return(NULL);
   }

//#ifdef POPEN_DEBUG
//printf("p_open(): &pids=%d count=%d pids[count]=%d exec program=%s\n", &pids, count, pids[count], program);
//#endif

//pthread_mutex_unlock(&popen_mutex);


if(pipe(pdes) < 0){
   return(NULL);
   }

switch(pid = vfork()){

// printf("P_POPEN(): PID=%d  exec program=%s\n", pid, program);

   case -1:  /* error */
      (void)close(pdes[0]);
      (void)close(pdes[1]);
      return(NULL);
      /* NOTREACHED */
   case 0:   /* child */
      if(*type == 'r'){
         if(pdes[1] != fileno(stdout)){
            if(out < 1 || out > 2){
               tes = dup2(pdes[1], fileno(stdout));
               }
            if(out == 1){
               tes = dup2(pdes[1], fileno(stdout));
               }
            if(out == 2){
               tes = dup2(pdes[1], fileno(stderr));
               }
            (void)close(pdes[1]);
            }
         (void)close(pdes[0]);
         }
      else{
         if(pdes[0] != fileno(stdin)){
            (void)dup2(pdes[0], fileno(stdin));
            (void)close(pdes[0]);
            }
         (void)close(pdes[1]);
         }

   setpgid(pid, pid);
   execve("/bin/sh", argv, NULL);
   _exit(127);

   }

/* parent; assume fdopen can't fail...  */
if(*type == 'r'){
   iop = fdopen(pdes[0], type);
   (void) close(pdes[1]);
   }
else{
   iop = fdopen(pdes[1], type);
   (void)close(pdes[0]);
   }

* pin = pid;
* gin = getpgid(pid);

if((fdno = fileno(iop)) < 0){
   return(NULL);
   }

//safe_pthread_mutex_lock(&popen_mutex);
//pids[count][fdno] = pid;
//pthread_mutex_unlock(&popen_mutex);


return (iop);
}




int p_pclose(FILE *iop, int pin, int count)
{
// register int fdes;
sigset_t omask, nmask;
// static int pstat;
int pstat;
register int pid;

/*
 * pclose returns -1 if stream is not associated with a
 * `popened' command, if already `pclosed', or waitpid
 * returns an error.
 */
//pthread_mutex_lock(&popen_mutex);
//safe_pthread_mutex_lock(&popen_mutex);

// printf("P_PCLOSE(): PID=%d START\n", pin);

if(pin <= 0){
   return (-1);
   }

(void)fclose(iop);
sigemptyset(&nmask);
sigaddset(&nmask, SIGINT);
sigaddset(&nmask, SIGQUIT);
sigaddset(&nmask, SIGHUP);
sigprocmask(SIG_BLOCK, &nmask, &omask);

do {
// printf("P_PCLOSE(): PID=%d wait4()待ち\n", pin);
   pid = wait4(pin, &pstat, 0, (struct rusage *)0);
   } while (pid == -1 && errno == EINTR);

sigprocmask(SIG_SETMASK, &omask, NULL);
// pids[count][fdes] = 0;

//#ifdef POPEN_DEBUG
//printf("p_pclose(): &pids=%d count=%d pids[count]=%d\n", &pids, count, pids[count]);
//#endif

//pthread_mutex_unlock(&popen_mutex);

// printf("P_PCLOSE(): PID=%d END\n", pin);

return (pid == -1 ? -1 : pstat);
}




