#include < stdio.h >
#include < signal.h >
#include < errno.h >
#define R (0)
#define W (1)
static struct pid {
struct pid *next;
FILE *fp;
pid_t pid;
} *pidlist;
FILE *popen_err(char *command,char *option)
{
struct pid *cur;
int pipe_c2p_e[2];
int pid;
FILE *fp;
if ((*option != 'r') || option[1]){
fprintf(stderr,"popen_err():option error:return(NULL)\n");
return (NULL);
}
if ((cur = (struct pid *)malloc(sizeof(struct pid))) == NULL){
fprintf(stderr,"popen_err():malloc error:return(NULL)\n");
return (NULL);
}
if(piep(pipe_c2p_e)<0){
perror("pipe");
return(NULL);
}
if((pid=fork())<0){
perror("fork");
close(pipe_c2p_e[R]);
close(pipe_c2p_e[W]);
return(NULL);
}
if(pid==0){
close(pipe_c2p_e[R]);
dup2(pipe_c2p_e[W],2);
close(pipe_c2p_e[W]);
execlp("sh","sh","-c",command,NULL);
_exit(127);
}
close(pipe_c2p_e[W]);
fp=fdopen(pipe_c2p_e[R],option);
cur->fp = fp;
cur->pid = pid;
cur->next = pidlist;
pidlist = cur;
return(fp);
}
int pclose_err(FILE *fp)
{
register struct pid *cur, *last;
#if BSD /* for */
int omask;
#else /* SYSV */
sigset_t set,omask;
#endif
int pstat;
pid_t pid;
extern int errno;
fclose(fp);
for(last = NULL, cur = pidlist; cur; last = cur, cur = cur->next){
if (cur->fp == fp){
break;
}
}
if (cur == NULL){
return (-1);
}
#if BSD /* for BSD */
omask = sigblock(sigmask(SIGINT|sigmask(SIGQUIT)|sigmask(SIGHUP));
do {
pid = waitpid(cur->pid, (int *) &pstat, 0);
} while (pid == -1 && errno == EINTER);
(void)sigsetmask(omask);
}
#else /* SYSV */
sigemptyset(&set);
sigaddset(&set,SIGINT);
sigaddset(&set,SIGQUIT);
sigaddset(&set,SIGHUP);
sigprocmask(SIG_SETMASK,&set,&omask);
do {
pid = waitpid(cur->pid, (int *)&pstat, 0);
} while (pid == -1 && errno == EINTR);
sigprocmask(SIG_SETMASK, &omask,NULL);
#endif
if (last == NULL){
pidlist = cur->next;
}
else {
last->next = cur->next;
}
free(cur);
return (pid == -1 ? -1 : pstat);
}