C linux: Simulate shell behavior with pipes


As the title indicates I am trying to perform an exercise to emulate the behavior of the shell in the execution of a sentence with the form comando1 argumento1 | comando2 argumento2 This program opens a pipe and creates a child by calling fork() , in addition the parent executes comando1 argumento1 and redirects the standard output to the writing end of the pipe. The child on the other hand executes comando1 argumento1 and in this case the standard input must be duplicated with the reading end of the pipe.

I am testing my program by executing ./shell echo holaa | wc -c , my program returns a 47, when I should return 6, since they are the chars of the word "hello" plus the end of file character '\ 0', and it is also what the linux shell returns if I run the command on it.

All help is welcome and thanks in advance, I leave the code of my program below, greetings.

#include <sys/types.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/select.h>
#include <stdlib.h>

// Probar el programa con ./shell echo holaa | wc -c
int main(int argc, char *argv[]) {
        if(argc < 6) {
                printf("Uso: comando1 argumento1 | comando2 argumento2\n");
        int descf[2]; //descf[0] -> lectura, descf[1] -> escritura
        int res1, res2;
        char *cmd1[] = {argv[1], argv[2], NULL};
        char *cmd2[] = {argv[4], argv[5], NULL};

        // Creamos la tuberia sin nombre
        // Si no ha habido errores (-1) fork() retorna dos veces, una con un pid = 0 (ejecución proceso hijo) y otra con un pid > 0 (ejecución proceso padre)
        pid_t pid = fork();
        if(pid == -1) {
                perror("Error en el fork()");
        } else if(pid > 0) { // Ejecución del padre:
                dup2(descf[0], 0); // Redirecciona salida estandar al extremo de escritura del pipe
                res1 = execvp(cmd1[0], cmd1); //Ejecuta comando1 argumento 1
                if(res1 == -1) perror("Fallo en execvp1()");
        } else if(pid == 0) { // Ejecución del hijo
                dup2(descf[1], 1); // Duplica la entrada estandar con el extremo de lectura del pipe
                res2 = execv(cmd2[0], cmd2); // Ejecuta comando2 argumento 2
                if(res2 == -1) perror("Fallo en execvp2()");
        return 0;
asked by DavidZam 28.06.2018 в 13:21

1 answer


"Uso: comando1 argumento1 | comando2 argumento2\n" has ... 47 characters! That match the value of 47 that the execution gives you. The coincidence indicates that the parameters do not go well with the 1 program.

The problem is that when doing


./ shell echo hello | wc -c

the linux shell itself sees the | and divides the instruction into two processes:

  • ./shell echo holaa

  • wc -c

and then you execute both, putting the shell itself the I / O chaining.

It could not be otherwise, since it needs that to detect the chaining, redirections, wildcards, etc.

To prevent the linux shell from interfering with your command, put it in quotation marks.


./ shell "echo hello | wc -c"

This will arrive as a single parameter to your executable and you will have to break it in tokens (first for the | , then for blank spaces 2 .

You could also do


./ shell echo hello "|" cat -

but since you're doing a "shell" it makes little sense.

As an additional note, it will be much more useful for you to do the test with cat - , which simply outputs your standard input by standard output:


./ shell echo hello | cat -

to see the error message.


./ shell "echo hello | cat -"

to see holaa (when you have adjusted your program).

1 If the result was 42, we could have suspected that this is a question related to the meaning of life, the universe and everything else .

2 By the way, the minimum limit of 6 arguments seems quite arbitrary. ls | wc is perfectly valid and useful, and only has 3.

answered by 28.06.2018 / 14:40