简体   繁体   English

ls | 用C编写的shell中的grep

[英]ls | grep in shell written in C

I am trying to make my own shell in C. It uses one pipe and the input (for now) is static. 我试图用C制作自己的shell。它使用一个管道,并且输入(目前)是静态的。 I execute commands using execvp. 我使用execvp执行命令。 Everything is fine except when I run the command ls |grep ".c" I get no results. 一切正常,除了运行命令ls |grep ".c"没有任何结果。 Can anyone show me where is the problem and find a solution. 谁能告诉我问题出在哪里并找到解决方案。

The shell so far: 到目前为止的外壳:

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

int   p[2];
int pid;
int r;

main()
{
    char *ls[] = {"ls", NULL};
    char *grep[] = {"grep", "\".c\"", NULL};

    pipe(p);

    pid = fork();
    if (pid  != 0) {
            // Parent: Output is to child via pipe[1]

            // Change stdout to pipe[1]
            dup2(p[1], 1);
            close(p[0]);

            r = execvp("ls", ls);
    } else {
            // Child: Input is from pipe[0] and output is via stdout.
            dup2(p[0], 0);
            close(p[1]);

            r = execvp("grep", grep);
            close(p[0]);
    }

    return r;
}

Remove the quotes in the argument to grep. 删除grep参数中的引号。 ie, use 即使用

char *grep[] = {"grep", ".c", NULL};

If you are calling execvp , the usual shell expansion of arguments (ie, globbing, removal of quotes, etc) does not happen, so effectively what you are doing is the same as 如果您正在调用execvp ,则不会发生参数的常规shell扩展(即,globbing,引号的删除等),因此实际上您所做的与

ls | grep '".c"'

In a normal shell. 在普通外壳中。

Also be aware that nothing that comes after the call to execvp will execute, execvp replaces the current process, it will never return. 另请注意,对execvp的调用之后不会执行任何操作, execvp 替换当前进程,它将永远不会返回。

You have multiple problems: 您有多个问题:

  1. One problem is that you have far too few calls to close() . 一个问题是您对close()调用太少了。 When you use dup2() to replicate a file descriptor from a pipe to standard input or standard output, you should close both file descriptors returned by pipe() . 当您使用dup2()将文件描述符从管道复制到标准输入或标准输出时,应关闭pipe()返回的两个文件描述符。

  2. A second problem is that the shell removes double quotes around arguments but you've added them around your. 第二个问题是外壳程序删除了参数周围的双引号,但是您已经在参数周围添加了双引号。 You are looking for files whose name contains ".c" (where the double quotes are part of the file name being searched for). 您正在寻找名称包含".c"文件(其中双引号是所搜索文件名的一部分)。 Use: 采用:

     char *grep[] = { "grep", "\\\\.c$", NULL }; 

    This looks for a dot and a c at the end of the line. 这会在行尾查找一个点和一个c

  3. You should report failures after execvp() . 您应该在execvp()之后报告失败。 If any of the exec*() functions returns, it failed. 如果任何exec*()函数返回,则失败。 It can happen when the user mistypes a command name, for example. 例如,当用户键入错误的命令名称时,可能会发生这种情况。 It is crucial that you report the error and that the child process then exits. 报告错误,然后子进程退出,这一点至关重要。 If you don't do that, you can end up in a normal iterative shell (rather than this one-shot, non-iterative, non-interactive shell) with multiple shell processes all trying to read from the terminal at the same time, which leads to chaos and confusion. 如果您不这样做,那么您可能会遇到一个普通的迭代外壳程序(而不是这种单发,非迭代,非交互的外壳程序),并且所有外壳程序进程都试图同时从终端读取数据,导致混乱和混乱。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM