Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1798334
  • 博文数量: 335
  • 博客积分: 4690
  • 博客等级: 上校
  • 技术积分: 4341
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-08 21:38
个人简介

无聊之人--除了技术,还是技术,你懂得

文章分类

全部博文(335)

文章存档

2016年(29)

2015年(18)

2014年(7)

2013年(86)

2012年(90)

2011年(105)

分类: C/C++

2012-03-14 23:16:21


  1. #include "apue.h"
  2. #include <errno.h>
  3. #include <fcntl.h>
  4. #include <sys/wait.h>

  5. /*
  6.  *pointer to array allocatied at run-time
  7.  */
  8. static pid_t * childpid = NULL;
  9. static int maxfd;

  10. FILE *
  11. popen( const char * cmdstring,const char * type)
  12. {
  13.     int i;
  14.     int pfd[2];
  15.     pid_t pid;
  16.     FILE * fp;
  17.     
  18.     /*
  19.          * only allow 'r' or 'w' */
  20.     if ( (type[0] != 'r' && type[0] != 'w') || type[1] != 0){
  21.         errno = EINVAL ;
  22.         return(NULL);
  23.     }
  24.     if (childpid == NULL) { /* first time through */
  25.         /*
  26.          * allocate zeroed out array for child */
  27.         maxfd = open_max();
  28.         if (( childpid = calloc(maxfd,sizeof(pid_t))) == NULL)
  29.             return(NULL);
  30.     }
  31.     if (pipe(pfd) <0)
  32.         return(NULL); /* errno set by pipe() */
  33.     if (( pid = fork()) < 0){
  34.         return(NULL);
  35.     } else if( pid == 0) {
  36.         if ( *type == 'r') {
  37.             close(pfd[0]);
  38.             if (pfd[1] != STDOUT_FILENO) {
  39.                 dup2(pfd[1],STDOUT_FILENO);
  40.                 close(pfd[1]);
  41.             }
  42.         } else {
  43.             close(pfd[1]);
  44.             if (pfd[0] != STDIN_FILENO) {
  45.                 dup2(pfd[0],STDIN_FILENO);
  46.                 close(pfd[0]);
  47.             }
  48.         }
  49.                /* close all descript in childpid[] */
  50.         for (i = 0 ; i < maxfd;i++)
  51.             if (childpid[i] > 0)
  52.                 close(childpid[i]);
  53.         execl("/bin/sh","sh","-c",cmdstring,(char *) 0);
  54.         _exit(127);
  55.     }
  56.     /* parent continue */
  57.         if (*type == 'r') {
  58.             close(pfd[1]);
  59.             if ((fp = fdopen(pfd[0],type)) == NULL)
  60.                 return(NULL);
  61.         } else {
  62.             close(pfd[0]);
  63.             if ((fp = fdopen(pfd[1],type)) == NULL)
  64.                 return(NULL);
  65.         }
  66.     childpid[fileno(fp)] = pid;
  67.     /* remeber childpid for this fd */
  68.     return(fp);
  69. }
  70. int pclose( FILE * fp)
  71. {
  72.     int fd,stat;
  73.     pid_t pid;
  74.     if (childpid == NULL) {
  75.         errno = EINVAL;
  76.         return(-1);
  77.     }
  78.     fd =fileno(fp);
  79.     if (( pid =childpid[fd]) == 0) {
  80.         errno = EINVAL;
  81.         return(-1); /* fp wasn't opened by popen() */
  82.     }
  83.     childpid[fd] = 0;   /* reset the pid to zero */
  84.     if (fclose(fp) == EOF)
  85.         return(-1);
  86.     while(waitpid(pid,&stat,0) <0)
  87.         if (errno != EINVAL)
  88.             return(-1); /* error other than EINVAL from waitpid() */
  89.     return(stat); /* return child's termination status */
  90. }
在每次调用popen的时候,需要记住fork进程的进程id,为此使用childpid来保存,还有就是文件描述符或是文件指针
在着就是要复制文件描述符到标准输入和标准输出
在关闭文件的时候,需要等待子进程结束,然后关闭文件描述符。










阅读(906) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~