Implement & background in my own shell in C?

3

I'm trying to create my own shell in C, so far I've gotten it to do everything I need correctly but I'm looking for ways to implement the asynchronous synchronization of when you type & behind a statement or command (also called background), the shell does not wait for the end of the child process but continues to wait for new user commands as the linux shell normally does. I leave my code to see if anyone can help me, I guess I have to do something with the waitpid. Thank you very much in advance.

PS: I also need that when writing & the PID of the process that is generated is shown, just as the unix shell does.

#include <stdio.h>
#include <stdlib.h>
#include <string.h> 
#include <unistd.h> 
#include <libgen.h> 
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <ctype.h>  

#define TAM 1000 

void  parseo(char *line, char **argv);
char* normalizar(char *str);

int main(void) {

    char  cad[TAM];             
    char  *argv[TAM]; 
    char  *to;

    pid_t pid;
    int status;

    while (1) {                   

        printf("user@PC $: ");    
        fgets(cad, TAM, stdin);

        // Si encontramos un salto de linea (se pulsa enter)
        if (cad[strlen(cad) - 1] == '\n')                                                           
            cad[strlen(cad) - 1] = '
#include <stdio.h>
#include <stdlib.h>
#include <string.h> 
#include <unistd.h> 
#include <libgen.h> 
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <ctype.h>  

#define TAM 1000 

void  parseo(char *line, char **argv);
char* normalizar(char *str);

int main(void) {

    char  cad[TAM];             
    char  *argv[TAM]; 
    char  *to;

    pid_t pid;
    int status;

    while (1) {                   

        printf("user@PC $: ");    
        fgets(cad, TAM, stdin);

        // Si encontramos un salto de linea (se pulsa enter)
        if (cad[strlen(cad) - 1] == '\n')                                                           
            cad[strlen(cad) - 1] = '%pre%';    // lo marcamos como final de sentencia    

        // Si no se escribe nada, se espera
        if (strlen(cad) == 0) continue;

        // Parseamos lo introducido en el shell
        parseo(cad, argv);

        // Normalizamos los comandos
        normalizar((char*)argv[0]);

        // Exit para salir del shell
        if (!strcmp(argv[0], "exit")) exit(0);  

        // Implementación del comando CD
        if (!strcmp(argv[0], "cd")){

            to = argv[1];
            // Retorno al directorio anterior
            if(argv[1] == NULL) chdir("..");

            chdir(to);
            continue;
        }            
        // Creamos el proceso
        pid = fork();

        if (pid  < 0) { 
            printf("Error al crear los procesos \n");
            exit(1);

        } else if (pid == 0) {   
            // Ejecutamos los comandos, a no ser que sea erroneo
            if (execvp(*argv, argv) < 0) {
                printf("%s: no se encontró la orden \n", argv[0]);
                exit(1);
            }
        }else {  

            waitpid(pid,&status,0);
        }   

    }
    return 0;
}

void  parseo(char *line, char **argv){

    while (*line != '%pre%') {       
        while (*line == ' ' || *line == '\t' || *line == '\n')

            *line++ = '%pre%';     
            *argv++ = line; 

        while (*line != '%pre%' && *line != ' ' && *line != '\t' && *line != '\n') 
            line++;             
    } 
    *argv = '%pre%';    
}

char* normalizar(char *str){

    unsigned char *p = (unsigned char *)str;

    while (*p) {
        *p = tolower((unsigned char)*p);
        p++;
    }

    return str;
}
'; // lo marcamos como final de sentencia // Si no se escribe nada, se espera if (strlen(cad) == 0) continue; // Parseamos lo introducido en el shell parseo(cad, argv); // Normalizamos los comandos normalizar((char*)argv[0]); // Exit para salir del shell if (!strcmp(argv[0], "exit")) exit(0); // Implementación del comando CD if (!strcmp(argv[0], "cd")){ to = argv[1]; // Retorno al directorio anterior if(argv[1] == NULL) chdir(".."); chdir(to); continue; } // Creamos el proceso pid = fork(); if (pid < 0) { printf("Error al crear los procesos \n"); exit(1); } else if (pid == 0) { // Ejecutamos los comandos, a no ser que sea erroneo if (execvp(*argv, argv) < 0) { printf("%s: no se encontró la orden \n", argv[0]); exit(1); } }else { waitpid(pid,&status,0); } } return 0; } void parseo(char *line, char **argv){ while (*line != '%pre%') { while (*line == ' ' || *line == '\t' || *line == '\n') *line++ = '%pre%'; *argv++ = line; while (*line != '%pre%' && *line != ' ' && *line != '\t' && *line != '\n') line++; } *argv = '%pre%'; } char* normalizar(char *str){ unsigned char *p = (unsigned char *)str; while (*p) { *p = tolower((unsigned char)*p); p++; } return str; }
    
asked by Michael Bueno 07.05.2017 в 16:24
source

1 answer

0

According to the waitpid documentation:

  

The waitpid function suspends the execution of the current process until   what          a child specified by the pid argument has ended, or until          produces a signal whose action is to end the current process or call          the handle function of the signal.

That is, what happens is that your process will stop until the end of the one you just invoked with & . Unless you want to develop all the logic to handle calls to processes in the background, an alternative would be to do something like this: system("ls &"); The problem with this is that you delegate the handling of the process to the original shell and not yours.

    
answered by 07.05.2017 в 17:33