用叉子execvp管和dup2的猫

时间:2014-01-26 14:22:39

标签: c fork pipe cat dup

这是我正在做的一系列练习中的一步。我写的程序应该有两个以上的参数。第一个参数的使用尚未实现。其余参数是目录列表。

在这一步中,我要做的是为参数中给出的每个目录创建一个cat实例,使用cat获取每个目录的所有文件的内容并打印内容。我应该能够处理/ home /目录和/ home /目录/两者之间的路径(使用最后一个/没有)

目前我正在做的是尝试使用参数/ home / directory / *运行cat,以便它将读取给定目录中的所有文件并返回它们的内容。这是我的代码:

#include "Step1.h"

int main(int argc,char* argv[])
{
    if(argc < 3)
    {
        printf("Usage: ./Step1 <exclusions file> <folder1> <folder2> <folder3> ...\n");
        return -1;
    }

    int i;
    for(i=2; i<argc; i++)
    {
        int catpipe[2];
        if(pipe(catpipe))
        {
            printf("Error in pipe\n");
            return -1;
        }
        pid_t pid = fork();
        if(pid < 0)
        {
            printf("Error in fork\n");
            return -1;
        }
        if(!pid)
        {
            dup2(catpipe[1],1); // cat pipe is used to get the output of cat program into this program.
            close(catpipe[1]);
            close(catpipe[0]);
            char* args[3];
            args[0] = "/bin/cat";
            int length = strlen(argv[i]);
            char* path;
            if(argv[i][length - 1] != '/') // the path given does not have the ending / 
            {
                path = malloc(length + 3);
                strcpy(path,argv[i]);
                path[length] = '/';      //append / at the end
                path[length+1] = '*';    // append * at the end
                path[length+2] = '\0';
            }
            else
            {
                path = malloc(length + 2); // the path contains the ending /
                strcpy(path,argv[i]);
                path[length] = '*';        // append * at the end
                path[length+1] = '\0';
            }                 
            args[1] = path;
            args[2] = NULL;
            printf("%s\n",path);
            execvp("/bin/cat",args);
        }
        close(catpipe[1]);
        char buffer[200];
        int total = read(catpipe[0],buffer,200); // read the output of cat program and print it. 
        buffer[total]='\0';
        printf("The buffer contains: %s\n",buffer);
    }
    return 0;
}

我按如下方式运行此代码:

mod@mod-Inspiron-N5110:~/project$ ./Step1 exclusions ./testdirectory1 ./testdirectory2/

我得到的结果是:

/bin/cat: ./testdirectory1/*: No such file or directory
The buffer contains: 
The buffer contains: ./testdirectory2/*

mod@mod-Inspiron-N5110:~/project$ /bin/cat: ./testdirectory2/*: No such file or directory

mod@mod-Inspiron-N5110:~/project$

但是当我这样做时:

mod@mod-Inspiron-N5110:~/project$ /bin/cat ./testdirectory1/*

结果是:

Testline 1 of testfile1 in testdirectory1
Test line 1 of testfile1 in testdirectory1
Testline 1 of testfile2 in testdirectory1
Testline 1 of testfile3 in testdirectory1

请帮我用我的程序获得这个结果。

提前致谢

2 个答案:

答案 0 :(得分:0)

所以基本上你在代码中出错的是你假设如果你将/directory/*作为cat的参数,cat会将其扩展为“多个文件”,而cat了解您要打开名为*的文件。

进行*扩展的简单方法是通过shell调用cat,它将从*扩展到“多个文件”。

要实现这一目标,您可以将execvp()替换为system(…)来电,这基本上是execl("sh", "sh", "-c", …, NULL),其中......是您的命令(即您只需拨打"/bin/sh", "-c", "/bin/cat", "/directory/*")即可应该通过shell扩展*

或者您可以使用自己的递归目录漫游算法,例如that one

答案 1 :(得分:0)

我想我找到了自己问题的答案。我发布这个相信有人像我一样会发现它有用的一天。但我还不是很擅长C.因此,如果这个答案是错误的,或者这里有一些错误/弱点,请随时纠正。

我的答案的关键是使用函数wordexp()。它可用于扩展给定路径:波形符,正则表达式,变量等。所以这是我的答案:

#include "Step1.h"

int main(int argc,char* argv[])
{
    if(argc < 3)
    {
        printf("Usage: ./Step1 <exclusions file> <folder1> <folder2> <folder3> ...\n");
        return -1;
    }

    int i;
    for(i=2; i<argc; i++)
    {
        int catpipe[2];
        if(pipe(catpipe))
        {
            printf("Error in pipe\n");
            return -1;
        }
        pid_t pid = fork();
        if(pid < 0)
        {
            printf("Error in fork\n");
            return -1;
        }
        if(!pid)
        {
            dup2(catpipe[1],1); // cat pipe is used to get the output of cat program into this program.
            close(catpipe[1]);
            close(catpipe[0]);

            int length = strlen(argv[i]);
            char* path;
            if(argv[i][length - 1] != '/') // the path given does not have the ending / 
            {
                path = malloc(length + 3);
                strcpy(path,argv[i]);
                path[length] = '/';      //append / at the end
                path[length+1] = '*';    // append * at the end
                path[length+2] = '\0';
            }
            else
            {
                path = malloc(length + 2); // the path contains the ending /
                strcpy(path,argv[i]);
                path[length] = '*';        // append * at the end
                path[length+1] = '\0';
            }            

        wordexp_t p;
        char **w;
            wordexp(path, &p, 0);
        char** args = malloc((p.we_wordc + 2) * sizeof(char*));
            args[0] = "/bin/cat";   
        w = p.we_wordv;
        int j;
        for (j = 0; j < p.we_wordc; j++)
        args[j+1] = w[j];                
            args[p.we_wordc + 1] = NULL;

            execvp("/bin/cat",args);
        }
        close(catpipe[1]);
        char buffer[1024];
        int total = read(catpipe[0],buffer,1024); // read the output of cat program and print it. 
        buffer[total]='\0';
        printf("The buffer contains: %s\n",buffer);
    }
    return 0;
}