【问题标题】:C - exec not outputting into pipeC - exec没有输出到管道中
【发布时间】:2014-11-02 10:03:08
【问题描述】:

我正在制作一个最终能够(理论上)为传递给它的任何 shell 命令工作的程序。我的问题是运行的 exec 不会将其输出放入管道中,而是在运行时似乎初始调用正在进入管道?我尝试先刷新标准输出,但它不起作用。任何帮助表示赞赏!

int main(int argc, char *argv[]) {

    int i=0, pid;
    int dataPipe[2];
    pipe(dataPipe);

    char *newArgs[5] = {"/bin/sh", "-c", "ls", "-a", NULL};

    if ((pid = fork()) < 0) {

        printf("Error: could not fork!");
        exit(2);
    }

    else if (pid == 0) {

        close(dataPipe[0]);
        fflush(stdout);

        dup2(dataPipe[1], 1);
        close(dataPipe[1]);

        if (execvp(newArgs[0], newArgs) < 0) {

            printf("Command Failed to exucute!");
            exit(3);
        }
    }

    else {

        char buf[BUFFER];
        close(dataPipe[1]);

        wait(0);
        printf("Command exexuted correctly!\n");

        while(read(dataPipe[0], buf, BUFFER) != 0) {
            printf("Here is the command's output:\n%s\n", buf);
        }

        exit(0);
    }

    return 0;
}

这是输出:

$ ./doit ls -a                                       
Command exexuted correctly!
Here is the command's output:
d
@
Here is the command's output:
o
@
Here is the command's output:
i
@
Here is the command's output:
t
@
Here is the command's output:
@
Here is the command's output:
d
@
Here is the command's output:
o
@
Here is the command's output:
i
@
Here is the command's output:
t
@
Here is the command's output:
.
@
Here is the command's output:
c
@
Here is the command's output:


@

【问题讨论】:

  • 请先告诉我们您观察到了什么。只是事实。 “程序打印‘对不起,朋友’并退出”。这是事实。 “输出不进入管道”。那将是一个理论。
  • 我确实说过 newArgs 出现了,但我会详细说明。输出如上。
  • 你应该使用{"/bin/sh", "-c", "ls -a", NULL}。但是,差异意味着您不会看到以点开头的名称。
  • 请检查您定义为BUFFER 的内容。检查您的输出后,我认为它非常小,(可能是 1 ?)也不是程序确实列出了您的文件 'doit' 和 'doit.c' (可能这些是您的工作主管中的两个)。
  • 1.将 BUFFER 增加到几百字节。 2.read不会对缓冲区进行空终止,需要自己做。

标签: c exec pipe stdout stdin


【解决方案1】:

你把一切都弄对了。您的代码只需进行几处更改即可使一切正常运行。

换行:

    while(read(dataPipe[0], buf, BUFFER) != 0) {
        printf("Here is the command's output:\n%s\n", buf);
    }

    printf("Here is the command's output:\n");
    while( (count = read(dataPipe[0], buf, BUFFER)) != 0) {
       fwrite(buf, count, 1, stdout);
    }

第一个变化,移动"Here is the command's output:\n" 的打印应该很明显。您不希望每次成功读取某些数据时都打印该行。

第二个变化有点微妙。

行:

printf("%s\n", buf);

与线路完全不同:

fwrite(buf, count, 1, stdout);

printf 方法存在几个问题:

  1. printf 调用中,每次成功完成read 都会在输出中引入换行符,而分叉进程的输出中没有这些换行符。

  2. printf 命令仅在 buf 是一个以 null 结尾的字符串时才有效。 read 不会创建以 null 结尾的字符串。使用read,您将获得一组原始字符。通过在预期以 null 结尾的字符串的位置使用 buf,您将调用未定义的行为。

使用fwrite 而不是printf 可以解决这两个问题。它不打印任何额外的换行符。它只打印从管道读取的确切字节数。

【讨论】:

  • 非常感谢!我应该意识到这是实际输出而不是我输入的命令,哈哈。
猜你喜欢
  • 2023-03-11
  • 1970-01-01
  • 1970-01-01
  • 2014-02-04
  • 2018-05-15
  • 2013-05-06
  • 1970-01-01
  • 1970-01-01
  • 2017-08-06
相关资源
最近更新 更多