How to make a pipe in your own shell?

2

I'm creating a UNIX and there was a question:

How to pipe in your own ? The command in String is a table respP

This is an idea but I have not managed to apply it:

if(tube==1){
      //printf("\n\n\n"); // En el caso de un pipe, mas de dos comandos debe ser ejecutado
    fich = open("fichtmp",O_RDONLY,0640);// se cree un fichero 
    close(0); //se cerra el teclador  
    dup(fich); //el fichero se convierto en la entredad 0 (el input) 
    execvp(respP[0], respP); se ejecuta la commanda
    close(fich); //se cerra el fichero
}

By comparison, this is the code with the case with no pipe.

if(tube==1){
      //printf("\n\n\n"); // En el caso de un pipe, mas de dos comandos debe ser ejecutado
    fich = open("fichtmp",O_RDONLY,0640);// se cree un fichero 
    close(0); //se cerra el teclador  
    dup(fich); //el fichero se convierto en la entredad 0 (el input) 
    execvp(respP[0], respP); se ejecuta la commanda
    close(fich); //se cerra el fichero
}
else if(output==0 && input==0){//no pipe 
    printf("truc1: Comando no encontrado");
    execvp(respP[0], respP);
}
    
asked by ThePassenger 08.01.2016 в 17:13
source

1 answer

1

Here is an example of the code that executes a pipe ls /etc/ | awk '{print $9, $5}' | grep '^profile' .

The output of each process is used for the input in the next process. The first process of the pipe has no entry (but could if necessary), and the output of the last process is read by the main process (your shell):

#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

#define MAX_ARGS 10 // FIXME debe ser dinámico

char* const cmds[][MAX_ARGS] = {
    { "ls", "-l", "/etc", NULL },
    { "awk", "{print $9, $5;}", NULL }, // columna $9 en ls salida es el nombre de fichero, $5 - su tamaño
    { "grep", "^profile", NULL },
};

// cerrar todos los descriptores abiertos desde 'start'
void cerrar_fds(int start) {
    // Hay métodos mejores para identificar cuales ficheros son abiertos,
    // mira en http://stackoverflow.com/questions/6583158/finding-open-file-descriptors-for-a-process-linux-c-code
    // pero es bastante para nuestros deberes
    int i;
    for(i = start + 1; i < 256; i++) {
            (void)close(i); // el éxito no importa
    }
}

pid_t ejec_part(char* const cmd[], int entrada, int* salida) {
    pid_t pid;
    int salidaPipe[2];
    if (pipe(salidaPipe) == -1) {
            perror("pipe");
            exit(98);
    }
    // ahora tenemos un pipe con dos lados, salidaPipe[0] es para leer
    // y salidaPipe[1] es para escribir

    pid = fork();
    if (pid == 0) { // proceso hijo
            if (entrada != -1) {
                    // dup2 es mejor que dup porque permite especificar
                    // a cual descriptor copiar el original
                    if (dup2(entrada, 0) == -1) {
                            perror("dup2");
                            exit(100);
                    }
            } else {
                    close(0);
            }
            // aquí salidaPipe[0] no se necesita
            close(salidaPipe[0]);
            // creamos una copia de salidaPipe[1] en FD == 1 (stdout)
            if (dup2(salidaPipe[1], 1) == -1) {
                    perror("dup2");
                    exit(100);
            }
            cerrar_fds(1);
            execvp(cmd[0], cmd);
            // normalmente no vamos hasta aquí
            perror("execvp");
            exit(101);
    } else if (pid < 0) { // error
            perror("fork");
            exit(99);
    } else {
            // en proceso padre salidaPipe[1] no se necesita
            close(salidaPipe[1]);
            *salida = salidaPipe[0];
            return pid;
    }
}

int main(void) {
    // ls no necesita la entrada, por eso usamos -1 para la entrada
    int entradaFd = -1;
    int salidaFd = -1;
    int numCmds = sizeof(cmds) / sizeof(cmds[0]);
    int i;
    for(i = 0; i < numCmds; i++) {
            ejec_part(cmds[i], entradaFd, &salidaFd);
            // un próximo proceso usa salidaFd del proceso anterior (el lado para leer)
            // como su entrada
            entradaFd = salidaFd;
    }
    {
            FILE* res = fdopen(entradaFd, "rb");
            int bufTam = 100;
            char* buf = malloc(bufTam);
            while(-1 != (getline(&buf, &bufTam, res))) {
                    printf("recibido de pipe: %s", buf);
            }
            fclose(res);
            free(buf);
    }
    return 0;
}
    
answered by 09.01.2016 / 06:57
source