0

機能に問題がありsystem()ます。

簡単な bash を実装する必要があります。私のプロジェクトのモジュールの 1 つは、ユーザーが bash コマンドを実行できるようにすることです。

私が実際にやっていることの上に:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// similar to gets
int reads(char* str)
{
#ifndef WIN32
    fflush(stdout);
    strcpy(str,GetServiceLine());
#else
    gets(str);
#endif

    return 1;
}

int main(void) {
    char str[100];

        while(strcmp(str, "exit")) {
            printf("\nNote: type \"exit\" to return menu\n");
            printf("MyBash$ ");
            reads(str);

            system(str);
        }

    return 0;
}

私の問題は、のようなコマンドにありますping

このコードを自分の PC で実行pingし、法的なコマンドを実行しようとすると、正常IPに動作しpingます。電話。CTRL+CCTRL+Csystem()

誰かが私を助けることができますか?

注:CTRL + Cを使用してシステム機能を中断する方法についてのこの投稿を読みました。提案を試みましたが、うまくいきませんでした。

ありがとう。

4

3 に答える 3

1

上記のコメントの後、なぜこれを優雅に制御できないのかを説明することを考えました(ただし、いくつかのハックがコメントで提案されています)。

system コマンドは、子プロセスを fork し、子で exec を呼び出して、引数として exec に渡されたバイナリを実行する場合とまったく同じように動作します。

system() 関数は、SIGINT および SIGQUIT シグナルを無視し、コマンドが終了するのを待っている間、SIGCHLD シグナルをブロックします。これにより、アプリケーションを強制終了するシグナルを見逃す可能性がある場合、アプリケーションは system() からの戻り値を調べて、適切なアクションを実行する必要があります。

これは非常に OS 固有の動作であり、そのような標準はありません。

Linux での system() 関数呼び出し

内部的に ping ユーティリティは icmp で実行され、他のノードから応答が受信されるまで待機します。

別の回答で提案されているようにシグナルハンドラーを作成して killpid() を呼び出すこともできますが、system() への呼び出しが戻るまでブロックされます。これは関数の仕様に記載されています。したがって、終了できる可能性がありますが、呼び出しが返された後にのみです。:)

于 2012-10-10T19:36:59.820 に答える
1

まだ試していないので、ここに提案として投げます。関心のあるシグナルをキャッチするためにシグナルハンドラをいつでもインストールできます。

これがどのように行われたかを示すコードを (ほとんど) 使用した簡単な例です。

#include <signal.h>
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h>   

void intHandler(int dummy) 
{
    exit(1);   // Do whatever you want here to handle it...
}

int main(void) 
{
    char str[100];
    signal(SIGINT, intHandler);   
    signal(SIGKILL, intHandler);
    while(strcmp(str, "exit")) {
       printf("\nNote: type \"exit\" to return menu\n");
       printf("MyBash$ ");
       gets(str);
       system(str);
    }      
    return 0; 
} 

これを使用してctrl + Cをキャッチできますが、それがあなたが探しているものかどうかはわかりません。

于 2012-10-10T19:27:14.127 に答える
0

私の問題を修正するために使用されたコードの下。どちらがより良い解決策かはわかりませんが、この場合は問題を解決しました。

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// similar to gets
int reads(char* str)
{
#ifndef WIN32
    fflush(stdout);
    strcpy(str,GetServiceLine());
#else
    gets(str);
#endif

    return 1;
}

void getCommandName(char input[], char output[])
{
    int count=0;

    while (input[count] != NULL && input[count] != ' ' && input[count] != '\0') {
        output[count] = input[count];
        count++;
    }
}

int killLastCommand(int pid)
{
    char commandKill[30];

    memset(commandKill, 0, 30);

    sprintf(commandKill, "kill -9 %d", pid);
    return(!system(commandKill));
}

int main(void) {
    FILE *fp; //Will be used with popen()
    char str[100];
    char lastCommandName[50];
    char pidofCommand[50];
    char strLastPIDCommand[10];
    int lastPIDCommand=0;

    memset (str, 0, 100);

        while(strcmp(str, "exit")) {
        if (lastPIDCommand == 0) {
            memset (lastCommandName, 0, 50); //Clean lastCommandName array
            memset (pidofCommand, 0, 50); //Clean pidofCommand array
            memset (strLastPIDCommand, 0, 10); //Clean strLastPIDCommand array

            printf("\n\nNote: type \"exit\" to return menu\n");
            printf("MyBash$ ");
                reads(str);

            if (strcmp(str, "exit")) {
                    sprintf(str, "%s &", str);
            }

            getCommandName(str, lastCommandName);

            system(str);
            sleep(1); //Sleep to guarantee than command will end

            sprintf(pidofCommand, "pidof %s", lastCommandName); 

            //Saving PID
            fp = popen(pidofCommand, "r");

            if (fp) {
                fgets(strLastPIDCommand, 10, fp);
                lastPIDCommand = atoi(strLastPIDCommand);
            } else {
                //Handle error
            }
            pclose(fp);

printf("commandName = %s\r\n", lastCommandName);
printf("pid = %d\r\n", lastPIDCommand);
        } else {
            printf("\n\nYou have a command running, press 'kill' to stop it before to type another command\n");
            printf("EITVBash$ \n\n");
            reads(str);

//          if (str[0] == 0x03) { //CTRL+C hexa code
            if (!strcmp(str, "kill")) {
                if (killLastCommand(lastPIDCommand)) {
                    lastPIDCommand = 0;
                }
            }
        }
    }

    return 0;
}

私の実装はおそらくクリーンではありませんが、cの経験はあまりありません。

みんなありがとう。

于 2012-10-11T14:15:29.857 に答える