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