- #include "apue.h"
- #include <errno.h>
- #include <fcntl.h>
- #include <sys/wait.h>
- /*
- *pointer to array allocatied at run-time
- */
- static pid_t * childpid = NULL;
- static int maxfd;
- FILE *
- popen( const char * cmdstring,const char * type)
- {
- int i;
- int pfd[2];
- pid_t pid;
- FILE * fp;
-
- /*
- * only allow 'r' or 'w' */
- if ( (type[0] != 'r' && type[0] != 'w') || type[1] != 0){
- errno = EINVAL ;
- return(NULL);
- }
- if (childpid == NULL) { /* first time through */
- /*
- * allocate zeroed out array for child */
- maxfd = open_max();
- if (( childpid = calloc(maxfd,sizeof(pid_t))) == NULL)
- return(NULL);
- }
- if (pipe(pfd) <0)
- return(NULL); /* errno set by pipe() */
- if (( pid = fork()) < 0){
- return(NULL);
- } else if( pid == 0) {
- if ( *type == 'r') {
- close(pfd[0]);
- if (pfd[1] != STDOUT_FILENO) {
- dup2(pfd[1],STDOUT_FILENO);
- close(pfd[1]);
- }
- } else {
- close(pfd[1]);
- if (pfd[0] != STDIN_FILENO) {
- dup2(pfd[0],STDIN_FILENO);
- close(pfd[0]);
- }
- }
- /* close all descript in childpid[] */
- for (i = 0 ; i < maxfd;i++)
- if (childpid[i] > 0)
- close(childpid[i]);
- execl("/bin/sh","sh","-c",cmdstring,(char *) 0);
- _exit(127);
- }
- /* parent continue */
- if (*type == 'r') {
- close(pfd[1]);
- if ((fp = fdopen(pfd[0],type)) == NULL)
- return(NULL);
- } else {
- close(pfd[0]);
- if ((fp = fdopen(pfd[1],type)) == NULL)
- return(NULL);
- }
- childpid[fileno(fp)] = pid;
- /* remeber childpid for this fd */
- return(fp);
- }
- int pclose( FILE * fp)
- {
- int fd,stat;
- pid_t pid;
- if (childpid == NULL) {
- errno = EINVAL;
- return(-1);
- }
- fd =fileno(fp);
- if (( pid =childpid[fd]) == 0) {
- errno = EINVAL;
- return(-1); /* fp wasn't opened by popen() */
- }
- childpid[fd] = 0; /* reset the pid to zero */
- if (fclose(fp) == EOF)
- return(-1);
- while(waitpid(pid,&stat,0) <0)
- if (errno != EINVAL)
- return(-1); /* error other than EINVAL from waitpid() */
- return(stat); /* return child's termination status */
- }
在每次调用popen的时候,需要记住fork进程的进程id,为此使用childpid来保存,还有就是文件描述符或是文件指针
在着就是要复制文件描述符到标准输入和标准输出
在关闭文件的时候,需要等待子进程结束,然后关闭文件描述符。
阅读(901) | 评论(0) | 转发(0) |