2016-03-30 5 views
-1

私は自分のシンプルなシェルを書いています。私がする必要があることは、シェルに残り、ctrl + cが押されたときに新しい行にプロンプ​​トを表示するだけで、SIGINTシグナルを制御することです。現在、私はシグナルを処理することができ、シェルは単にプロンプ​​トの後に^Cを表示します。ただし、カーソルは同じ行に残ります。私が代わりにしたいのは、プロンプトの後にシェルプリント^Cを入れ、次の行に移動し、新しいプロンプトを表示します。私自身のシェルを書く - Ctrl + C(SIGINT)を正しく処理することの問題

正確に同じ問題に対処するthis questionが見つかりました。私の問題は、私のmainがプロンプトループが実行される別の機能を呼び出すことです。上記のリンク上で、メインとプロンプトのループ機能の両方で解決策を実装しようとすると、多くの異なる方法を試しましたが、すべては不運です。ここに私のコードは、これまでのところです:

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

使用:

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

は、ctrl + cが最初に押されたときに機能しますが、それ以降は押されたときのように動作します。

+0

"issue"という名前のものは実際に表示されません。空の入力で1回のループ反復を実行するだけです。はい、コードの重複を避けるために、要素を並べ替える必要があります。 @EugeneSh。 –

+0

。それも私が思いついた1つの解決策でしたが、ユーザーの入力がなくてもループを実行することはできませんでした。どうすればこれを達成できますか? – KOB

+0

ループの内容を別の関数に取り込みます。あるいは、入力用に1つ、出力用に2つに分かれています。次に出力用に呼び出します。 –

答えて

0

signalは、受信した最初の適切な信号に対してのみハンドラを接続します。その呼び出しの後、ハンドラーは切り離されます。一般的な方法は、ハンドラをint foo() { signal(SIGINT, &foo); do_the_stuff(); }のように再接続させることです。

ただし、signal is non-portableです。 POSIXではsigactionを代わりに使用することを推奨しています。

+0

あなたの最初の解決策は私のケースでは 'signal'が' main'で呼び出されているためではありません - 私はこれを正しく言いますか? – KOB

+0

あなたはまだメインでも、どこでも、一度だけ、最初に信号を呼ぶでしょう。その後シグナルが捕捉されるたびに、ハンドラは自身のボディ内のシグナルを呼び出すことによってそれ自体を再接続します。 –

+0

私はシグナルの機能が貧弱なために、これでどこに行っても本当に苦労しています。私は 'signal(SIGINT、ctrl_C_handler)'を呼び出すのと同じように私の 'main'メソッドを持っています。それでは、私は 'void ctrl_C_handler(){signal(SIGINT、ctrl_C_handler)}'を持っていますが、新しいプロンプトを表示せずに '^ C'だけを表示しています。私はこれに何を加えなければならないのですか? – KOB

関連する問題