Advanced Programming in UNIX Environment Episode 86

popen and pclose Functions

Since a common operation is to create a pipe to another process to either read its output or send it input, the standard I/O library has historically provided the popen and pclose functions.

#include <stdio.h>
FILE *popen(const char *cmdstring, const char *type);
int pclose(FILE *fp);

The cmdstring is executed by the Bourne shell, as in

sh -c cmdstring

This means that the shell expands any of its special characters in cmdstring. This allows us to say, for example,

fp = popen("ls *.c", "r");

or

fp = popen("cmd 2>&1", "r");
#include "apue.h"
#include <sys/wait.h>

#define PAGER "${PAGER:-more}"

int main(int argc, char *argv[])
{
    char line[MAXLINE];
    FILE *fpin, *fpout;

    if(argc!=2)
        err_quit("usage: a.out <pathname>");
    if((fpi=fopen(argv[1],"r"))==NULL)
        err_sys("can't opne %s", argv[1]);
    
    if((fpout=popen(PAGER,"w"))==NULL)
        err_sys("popen error");
    
    while(fgets(line,MAXLINE,fpin)!=NULL)
    {
        if(fputs(line,fpout)==EOF)
            err_sys("fputs error to pipe");
        if(pclose(fpout)==-1)
            err_sys("pclose error");
    }

    return 0;
}

Copy file to pager program using popen

#include "apue.h"
#include <sys/wait.h>
#include <fctnl.h>
#include <errno.h>

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;

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

    if(childpid==NULL)
    {
        maxfd=open_max();
        if((childpid=calloc(maxfd, sizeof(pid_t))==NULL))
            return NULL;
    }

    if(pipe(pfd)<0)
        return NULL;
    if(pfd[0]>=maxfd||pfd[1]>=maxfd)
    {
        close(pfd[0]);
        close(pfd[1]);
        errno=EMFILE;
        return NULL;
    }

    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]);
            }
        }

        for(i=0;i<maxfd;i++)
            if(childpid[i]>0)
                close(i);

        execl("/bin/sh", "sh", "-c",cmdstring, (char *0));
        _exit(127);
    }

    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;
    return fp;
}

int pclose(FILE *fp)
{
    int fd, stat;
    pid_t pid;

    if(childpid==NULL)
    {
        errno=EINVAL;
        return -1;
    }

    fd=fileno;
    if(fd>=maxfd)
    {
        errno=EINVAL;
        return -1;
    }

    if((pid=childpid[fd])==0)
    {
        errno=EINVAL;
        return -1;
    }

    childpid[fd]=0;
    if(close(fp)==EOF)
        return -1;

    while(waitpid(pid,&stat, 0)<0)
        if(errno!=EINTR)
            return -1;
    
    return stat;
}

The popen and pclose functions

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值