2016-03-30 1 views
-1

J'écris mon propre shell simple. Une chose que je dois faire est de contrôler le signal SIGINT en restant dans le shell et en imprimant simplement l'invite sur une nouvelle ligne lorsque ctrl + c est pressé. Actuellement, j'ai été capable de gérer le signal et le shell imprime simplement ^C après l'invite. Cependant, le curseur reste sur la même ligne. Ce que je voudrais faire à la place est d'imprimer le shell ^C après l'invite, passer à la ligne suivante et imprimer une nouvelle invite. J'ai trouvé this question, qui corrige exactement le même problème. Le problème avec le mien est que mon main appelle une autre fonction où la boucle d'invite est exécutée. J'ai essayé plusieurs façons d'implémenter la solution donnée sur le lien ci-dessus, à la fois dans la fonction principale et dans la fonction de boucle rapide, mais sans aucune chance. Voici mon code à ce jour:Écrire mon propre shell - problème avec la gestion correcte de ctrl + c (SIGINT)

Main.c

#include <stdio.h> 
#include <stdlib.h> 
#include <signal.h> 
#include "MyShell.h" 

void ctrl_C_handler(); 

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

    signal(SIGINT, ctrl_C_handler); 
    my_shell_loop(); 

    return EXIT_SUCCESS; 
} 

void ctrl_C_handler() { 
    //Catches the SIGINT signal fine without anything happening in this function 
    //I cannot figure out how to have MyShell print a fresh prompt on a new line 
    //after ctrl+C is pressed 
} 

MyShellLoop.c

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <time.h> 
#include "MyShell.h" 

char *get_time(); 

void my_shell_loop() { 
    char *line; 
    char **args; 
    int status; 

    char *prompt = (char *) malloc(17); 

    do { 
     strcpy(prompt, get_time()); 
     strcat(prompt, " # "); 
     printf("%s", prompt); 
     line = read_command(); 
     args = split_command(line); 
     status = execute_command(args); 

     free(line); 
     free(args); 
    } while (status); 

    free(prompt); 
} 

EDIT

utilisant:

void ctrl_C_handler() { 
    signal(SIGINT, ctrl_C_handler); 
    printf("\n"); 
    my_shell_loop(); 
} 

agit comme on le souhaite la première fois que ctrl + c est pressé, mais agit ensuite comme il le faisait auparavant pour toutes les fois où il est pressé.

+0

Je ne vois vraiment rien qui puisse être nommé "problème". Il suffit d'effectuer une itération de boucle avec une entrée vide. Oui, vous devrez réarranger les choses pour éviter la duplication de code. –

+0

@EugeneSh. C'est une solution que j'ai trouvée moi aussi, mais je n'ai pas pu faire une boucle sans intervention de l'utilisateur. Comment pourrais-je y parvenir? – KOB

+0

Prendre le contenu de la boucle dans une fonction séparée. Ou mieux à deux - un pour l'entrée, un pour la sortie. Ensuite, appelez simplement celui pour la sortie. –

Répondre

0

signal attache un gestionnaire uniquement pour le premier signal approprié qui est reçu. Après cette invocation, le gestionnaire est détaché. Une méthode courante consiste à ce que le gestionnaire se reconnecte comme dans int foo() { signal(SIGINT, &foo); do_the_stuff(); }.

Cependant, signal is non-portable. POSIX recommande d'utiliser sigaction à la place.

+0

Votre première solution n'est pas possible dans mon cas car 'signal' est appelé dans' main' - ai-je raison de le dire? – KOB

+0

Vous appelez toujours le signal la première fois, en principal ou ailleurs, juste une fois. Chaque fois que le signal est capturé par la suite, le gestionnaire se reconnecte en appelant le signal dans son propre corps. –

+0

J'ai vraiment du mal à obtenir n'importe quoi avec ceci en raison de ma mauvaise compréhension de la fonction 'signal'. J'ai ma méthode 'main' comme ci-dessus, en appelant' signal (SIGINT, ctrl_C_handler) '. Ensuite, j'ai votr 'ctrl_C_handler() {signal (SIGINT, ctrl_C_handler)} ', mais il est toujours en train d'imprimer'^C' sans imprimer la nouvelle invite. Quoi d'autre dois-je ajouter à cela? – KOB