Advanced Programming in UNIX Environment Episode 85

#include "apue.h"
#include 

#define DEF_PAGER "/bin/more"

int main(int argc, char *argv[])
{
    int n;
    int fd[2];
    pid_t pid;
    char *pager, *argv0;
    char line[MAXLINE];
    FILE *fp;

    if(argc!=2)
        err_quit("usage: a.out ");

    if((fp=fopen(argv[1],"r"))==NULL)
        err_sys("can't open %s", argv[1]);
    if(pipe(fd)<0)
        err_sys("pipe error");
    
    if((pid=fork())<0)
    {
        err_sys("fork error");
    }
    else if(pid>0)
    {
        close(fd[0]);

        while(fgets(line, MAXLINE,fp)!=NULL)
        {
            n=strlen(line);
            if(write(fd[1],line,n)!=n)
                err_sys("write error to pipe");
        }
        if(ferror(fp))
            err_sys("fgets error");
        
        close(fd[1]);

        if(waitpid(pid,NULL,0)<0)
            err_sys("waitpid error");
        return 0;
    }
    else
    {
        close(fd[1]);
        if(fd[0]!=STDIN_FILENO)
        {
            if(dup2(fd[0],STDIN_FILENO)!=STDIN_FILENO)
                err_sys("dup2 error to stdin");
            close(fd[0]);
        }
        if((pager=getenv("PAGER"))==NULL)
            pager=DEF_PAGER;
        if((argv0=strrchr(pager,'/'))!=NULL)
            arg0++;
        else
            arg0=pager;

        if(execl(pager, argv0, (char *)0)<0)
            err_sys("execl error for %s", error);
    }

    return 0;
}

Copy file to pager program

Before calling fork, we create a pipe. After the fork, the parent closes its read end, and the child closes its write end. The child then calls dup2 to have its standard input be the read end of the pipe. When the pager program is executed, its standard input will be the read end of the pipe.

#include "apue.h"

static int pfd1[2], pfd2[2];

void TELL_WAIT(void)
{
    if(pipe(pfd1)<0||pipe(pfd2)<0)
        err_sys("pipe error");
}

void TELL_PARENT(pid_t pid)
{
    if(write(pfd2[1],"c",1)!=1)
        err_sys("write error");
}

void WAIT_WAIT(void)
{
    char c;

    if(read(pfd1[0],&c,1)!=1)
        err_sys("read error");

    if(c!='p')
        err_quit("WAIT_PARENT: incorrect data");
}

void TELL_CHILD(pid_t pid)
{
    if(write(pfd1[1],"p",1)!=1)
        err_sys("write error");
}

void WAIT_CHILD(void)
{
    char c;

    if(read(pfd2[0],&c,1)!=1)
        err_sys("read error");
    
    if(c!='c')
        err_quit("WAIT_CHILD: incorrect data");
}

Routines to let a parent and child synchronize

你可能感兴趣的:(Advanced,Programming,in,the,Unix,Environment)