Using bc through pipes and fork


I’m trying to get the answer of a char expression using bc through pipes.
I would like first to write the expression in the pipe1, which the bc will read and write the answer in pipe2. For this I am changing the input and output. This does work if I do not use a char[] and just put the expression in the write :

write(pipe1[1], "20*5\n", sizeof("20*5\n")-1) != sizeof("20*5\n")-1)

But if I declare a tab, I keep getting the error :

(standard_in) 2: illegal character: ^@

Sometimes it is 1 instead of 2

What I am doing wrong? If someone could explain me, thank you.

Code :

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

int main(void)
    char resultat[5];
    int pipe1[2];
    int pipe2[2];


    int resultat_fork = fork();

    if (resultat_fork == -1)

    char* expression = "20*5\n";

    if (resultat_fork != 0)
        //printf("I am the parent\n");


        if (write(pipe1[1], expression, sizeof(expression)) != sizeof(expression))
            fprintf(stderr, "write to child failed\n");

        int nbytes = read(pipe2[0], resultat, sizeof(resultat));
        if (nbytes <= 0)
            fprintf(stderr, "read from child failed\n");
            printf("resultat: %.*s\n", nbytes, resultat);

        printf("I am the child\n");

        dup2(pipe1[0], 0);
        dup2(pipe2[1], 1);
        close(pipe1[0]);    /* More closes! */
        close(pipe2[1]);    /* More closes! */

        execlp("bc", "bc", NULL);
        fprintf(stderr, "Failed to execute bc\n");
    return 0;


The variable expression is a pointer, not an array. Use strlen() instead of sizeof. (I did mention using strlen() in commentary to my previous answer to a previous variant of this question.)



^@ is the nul character i.e. '\0'. This would suggest you are overrunning the end of the string when you write it to bc. The problem is here:


expression is not an array, it is a char pointer that points to the first character of the string "20*5\n" and, if you are on a 64 bit machine, its size is 8. To get the length of the string to send, use strlen(expression) instead.

Another thing you need to do, not related to your problem is, in the parent process, after you’ve read the answer, wait for the child process to finish. Otherwise, you’ll be left with a zombie.



This is wrong

if (write(pipe1[1], expression, sizeof(expression)) != sizeof(expression))

You are using sizeof operator with expression which is a char*, if your system is 32-bit, it will result in 4, which is the size of any pointer variable in your code.

You need to use strlen(expression) instead of sizeof.

As pointed out in the answer as well, you need to wait for child process to finish its execution and terminate, if the parent process has more than one child processes. Ideally, you should also check the return value of wait, which provides you more context on how the child process was terminated.



Tags:, , ,

Add a Comment