通过C中的管道向bc写一个术语

时间:2016-12-06 12:14:28

标签: c pipe bc

我遇到了这个C练习的问题。 任务是创建两个进程。两者连接两个管道,终止于孩子的stdin和stdout。然后用bc替换子进程。 然后我应该从父进程到子进程(bc)写一个术语(例如1 + 2)。

管道正在做他们应该做的事情,但是,bc似乎并不喜欢输入。当我写入管道时,bc会响应以下多行:

(standard_in) 1: illegal character: ^@

到目前为止,这是我的解决方案:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

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

    /*Create two pipes:
        One from parent to child (pipe_pc)
        and one from child to parent (pipe_cp).
    */
    int pipe_pc[2], pipe_cp[2];

    int cid;

    if (pipe(pipe_pc) == -1 || pipe(pipe_cp) == -1) {
        printf("Could not pipe\n");
        exit(EXIT_FAILURE);
    }

    // Create child process
    cid = fork();

    if (cid == -1) {
        printf("Could not fork.\n");
        exit(EXIT_FAILURE);
    }

    // Child process
    if (cid == 0) {

        // Redirect pipes
        close(STDOUT_FILENO);
        close(STDIN_FILENO);
        close(pipe_pc[1]); // Close writing end
        close(pipe_cp[0]); // Close reading end

        dup2(pipe_pc[0], STDIN_FILENO); // Take stdin from parent
        dup2(pipe_cp[1], STDOUT_FILENO); // Give stdout to parent

        int err;

        // Replace child with bc
        err = execl("/usr/bin/bc", "bc --quiet", (char*) NULL);

        printf("%s %d\n", "Could not start bc:", err);
        exit(err);
    }

    // Parent Process
    else {

        char input[128] = "";
        char buffer[128] = "";

        printf("%s\n", "Parent process running");

        // Copy argv to a single string
        for(int i=1; i < argc; i++) {
            strcat(input, argv[i]);
        }

        // Write the input to the child's stdin
        write(pipe_pc[1], input, sizeof(input);

        // Read the child's stdout
        read(pipe_cp[0], buffer, sizeof(buffer));

        printf("Result: %s\n", buffer);

        return 0;
    }

}

提前感谢提示和帮助,非常感谢!

2 个答案:

答案 0 :(得分:0)

您的代码有很多未定义的行为。

write(pipe_pc[1], input, sizeof(input);

您编写所有输入数组。但是你只需要用strcat()写下你复制的内容。 使用strlen。

write(pipe_pc[1], input, strlen(input));
strcat(input, argv[i]);

在这里你应该确认你不会超过128个八位字节。

if (strlen(input) + strlen(argv[i]) + 1 > 128) {
  break;
}
strcat(input, argv[i]);
read(pipe_cp[0], buffer, sizeof(buffer));

这里你不验证缓冲区是否是有效的c字符串。

ssize_t ret = read(pipe_cp[0], buffer, sizeof(buffer) - 1);
if (ret < 0)
  return 1;
buffer[ret] = '\0';

您忘记关闭父

中的管道
close(pipe_pc[0]);
close(pipe_cp[1]);

并在您的读/写之后

close(pipe_pc[1]);
close(pipe_cp[0]);

您忘了在dup2()

之后关闭孩子的管道
close(pipe_pc[1]);
close(pipe_cp[0]);

你不需要在dup2之前关闭旧的fd,他会为你做。而且,您不会检查dup2()

的错误

答案 1 :(得分:0)

问题是你没有在管道中正确写入,所以bc收到了错误的输入。

我重写了else分支。

如果您不确定在管道中发送了什么,请使用0(i / o fd)临时替换管道描述符,并直观地检查您的操作。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

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

    /* Create two pipes: One from parent to child (pipe_pc) and one
       from child to parent (pipe_cp).
    */
    int pipe_pc[2], pipe_cp[2];

    int cid;

    if (pipe(pipe_pc) == -1 || pipe(pipe_cp) == -1) {
        printf("Could not pipe\n");
        exit(EXIT_FAILURE);
    }

    // Create child process
    cid = fork();

    if (cid == -1) {
        printf("Could not fork.\n");
        exit(EXIT_FAILURE);
    }

    // Child process
    if (cid == 0) {

        // Redirect pipes
        close(STDOUT_FILENO);
        close(STDIN_FILENO);
        close(pipe_pc[1]); // Close writing end
        close(pipe_cp[0]); // Close reading end

        dup2(pipe_pc[0], STDIN_FILENO); // Take stdin from parent
        dup2(pipe_cp[1], STDOUT_FILENO); // Give stdout to parent

        int err;

        // Replace child with bc
        err = execl("/usr/bin/bc", "bc --quiet", (char*) NULL);

        printf("%s %d\n", "Could not start bc:", err);
        exit(err);
    }

    // Parent Process
    else {
        char buffer[128] = "";

        // printf("%s\n", "Parent process running");

        for(int i=1; i < argc; i++)
            write(pipe_pc[1], argv[i], strlen(argv[i]));

        write(pipe_pc[1], "\n", 1);

        read(pipe_cp[0], buffer, sizeof(buffer));

        printf("Result: %s\n", buffer);

        return 0;
    }

}