2009-08-24 2 views
3

私はコマンドを求めるプロンプトを出そうとしていますが、execを使ってそのコマンドを実行しようとしています。unixのユーザ入力でCでexecvp()を使用しようとしています

例えば、彼らが私に "ls -la"を与えた場合、私はそのコマンドを実行する必要があります。私は、次のコードを試してみた:

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

int main() 
{ 

    int ret, num_args; 

    printf("Enter number of arguments (Example: \"ls -la\" has 1 argument): "); 
    scanf("%d", &num_args); 

    char *cmd[num_args]; 

    printf("Enter command name: "); 
    scanf("%s", &cmd[0]); 

    int i; 
    for (i = 0; i < num_args; i++) 
    { 
      printf("Enter parameter: "); 
      scanf("%s", &cmd[i]); 
    } 

    execvp(cmd[0], cmd); 
} 

しかし、私はそれが私に「セグメンテーション違反」

$ ./a.out 
Enter number of arguments (Example: "ls -la" has 1 argument): 2 
Enter command name: ls 
Enter parameter: -la 
Enter parameter: . 
Segmentation fault 
$ 

任意のアイデアを与えた次の実行をしようとしたとき?

答えて

3

実装でサポートされている場合は、scanf()またはfgets()ではなく、より安全なgetline()を使用する必要があります。 getline()は、長い行とNULL文字を安全に処理します。それは、行全体に収まるのに十分なメモリを割り当てます。 getline()はメモリを割り当てることができますので、後で自分でメモリを解放する必要があります。

ここにはglibc getline() documentationがあります。ここで

は(それはまだ作業が必要、エラーチェックと、私はまだ完全には正しさのためにそれをチェックしていない)のgetlineを使用するための簡単な修正である:

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

int main() 
{ 

    printf("Enter number of arguments (Example: \"ls -la\" has 1 argument): \n"); 

    char *num = NULL; 
    size_t sz = 0; 
    getline(&num, &sz, stdin); 

    int num_args; 
    sscanf(num, "%d", &num_args); 

    char *cmd[num_args+2]; 
    memset(cmd, 0, sizeof(char*) * (num_args+2)); 

    printf("Enter command name: \n"); 


    int len = getline(&cmd[0], &sz, stdin); 

    cmd[0][len-1] = '\0'; 

    int i; 
    for (i = 1; i < num_args+1; i++) 
    { 
     printf("Enter parameter: \n"); 
     sz = 0; 
     len = getline(&cmd[i], &sz, stdin); 
     cmd[i][len-1] = '\0'; 
    } 

    return execvp(cmd[0], cmd); 

} 
+0

コンパイラはgetl​​ineが何であるか分からないようですが、これは#include行がないか、コンパイラ自体のためですか? –

+0

'getline'はCのGNU関数です:http://www.gnu.org/s/libc/manual/html_node/Line-Input.html –

+0

コンパイラとは何ですか? –

1

cmd配列が指す文字列に実際にメモリを割り当てていません。

+1

私はこれをどのように正確に行うのですか? –

+1

malloc/freeを検索し、 "cmd"の各ポインタに十分なスペースが割り当てられていることを確認してください。 –

2

argvに1つ以上のエントリが必要です。execvpに渡す必要があります。これは、リストの最後に到達したことを知らせるために(char *)NULLでなければなりません。

+0

そしてもう一つはコマンドの名前であるargv [0](通常)です。 –

3

文字列にメモリを割り当てる必要があります。あなたは(コマンド自体はcmd[0]であることを忘れないでください)num_args + 1文字列を取得することがあります、すべての

char *cmd[num_args]; 

まず次の行にのみcharへのポインタのnum_args価値を割り当てます。最も簡単な方法は、静的文字バッファの配列としてメモリを割り当てることです。しかし

const unsigned int MAX_LEN = 512; // Arbitrary number 
char cmd[num_args + 1][MAX_LEN]; 

、ユーザーが入力し、あなたの文字バッファより長いです文字列を可能性があるため、今あなたが行を読み込むことscanfを使用することはできません。

fgets(cmd[i], MAX_LEN, stdin); 

fgetsも改行文字を読み取って、その表示の浮遊ものを除去することを確認していることに注意してください:入力できる代わりに、ユーザーの文字の数を制限することができ、fgetsを使用する必要があります(しかし、彼らがそこにいるとは思わない)。

+0

そのようにしてみると、コンパイルエラーがたくさん出てきました。それはcmd [num_arghs + 1] [MAX_LEN]です。正しくありません: "構文エラーの前に ';'" –

+0

@ニックコードをダブルチェックしてください。私は小さなテストプログラムを書いて、それは私のためにうまくコンパイルされました。 –

+0

私は 'MAX_LEN = 512'行でセミコロンを忘れました。今修正されました。 –

-1

は(scanf関数のmanページを見てみましょう)。それができる最もきれいなことの1つは、自動的に文字列バッファを即座に割り当てることです。単に文字列を渡す代わりに文字列へのポインタを指定し、%を書式として指定する必要があります。

char *my_string; 
scanf("%as", &my_string); 

次に、あなたがそれで終わった後だけ)(解放するためにそれを覚えてなど、バッファオーバーフローを気にする必要はありません、事前割り当てを気にする必要はありません。

+0

'%as'仕様は標準ではありませんが、役に立つかもしれません。 –

関連する問題