1

シェルを実行すると、" Shell>" というプロンプトが表示されます。のようなコマンドを入力するlsと、" " という新しい行がShell>再び作成されます。

ヒットしていないように見える理由はありexecvますか?

            int no_of_args = count(buffer);
            // plus one to make it NULL
            char** array_of_strings = malloc((sizeof(char*)*(no_of_args+1)));

            //  break the string up and create an array of pointers that
            // point to each of the arguments.
            int count=0;
            char* pch2;
            pch2 = strtok (buffer," ");
            while (pch2 != NULL)
            {
                array_of_strings[count]=(char*)malloc((sizeof(char)*strlen(pch2)));
                strcpy(array_of_strings[count], pch2);

                pch2 = strtok (NULL, " ");
                count++;
            }

            //format for command is eg. ls -a -l
            //therefore the first element in the array will be the program name
            //add the path so it'll be /bin/command eg. /bin/ls
            char* prog = malloc(sizeof(char)*(strlen(array_of_strings[0]+strlen(path))));
            prog = strcat(strcpy(prog, path),array_of_strings[0]);


}
4

3 に答える 3

3

まず最初に、常に 1 であるため、使用する必要はありません。sizeof(char)

ISO C99 では、次のようにバイトが定義されています。

実行環境の基本文字セットの任意のメンバーを保持するのに十分な大きさのデータ ストレージのアドレス指定可能な単位。

およびそれ以降の状態6.5.3.4 The sizeof operator:

型 char、unsigned char、または signed char (またはその修飾バージョン) を持つオペランドに適用されると、結果は 1 になります。

これは C11 でも変更されていません。

したがって、基本的に、バイトはchar. ISO は通常、この用語octetを 8 ビット値用に予約しています。


次に、次のようなステートメント シーケンスです。

array_of_strings[count]=(char*)malloc((sizeof(char)*strlen(pch2)));
strcpy(array_of_strings[count], pch2);

が指す文字列のコピーを格納するのに十分なスペースが不足しているため、未定義の動作strlen(pch2)です。次のようなものを使用する必要があります。pch2

array_of_strings[count] = malloc (strlen (pch2) + 1);

また、キャストを削除したことにも気付くでしょう。C ではメモリ割り当て関数の戻り値をキャストしないでください。状況によっては問題が隠される可能性があるためです。

argv第三に、配列のルールに従っていないようです。ls x.txtコマンドが生成するように、この配列の最後の要素は NULL ポインターである必要があります。

  • "ls".
  • "x.txt".
  • NULL.

さて、あなたの特定の問題に進みましょう。execv実行可能ファイルが実行される保証がないため (たとえば、ディレクトリlsにない場合) 、呼び出しからの戻り値を確認する必要があります。/bin私なら、変えるね:

int rv = execv(prog, array_of_strings);

の中へ:

printf ("DEBUG: [%s]\n", prog);
int rv = execv(prog, array_of_strings);
printf ("DEBUG: execv returned %d/%d\n", rv, errno); // need errno.h

デバッグ目的で、それが何を出力するかを確認してください。

execvうまくいけば、その最終メッセージは表示されません。execv表示された場合は、機能しなかった理由が表示されます。これを行うと、次のように表示されます。

DEBUG: [/bin/ls
]
DEBUG: execv returned -1/2

つまり、実行しようとしている実行可能ファイルの名前は/bin/lsXで、Xは改行文字です。そのような実行可能ファイルがないため、エラー 2 ( ENOENT = No such file or directory) からexecv- 改行が残らないように解析コードを修正する必要があります。

簡単なデバッグ修正として、次の行を変更しました。

prog = strcat(strcpy(prog, path),array_of_strings[0]);

の中へ:

prog = strcat(strcpy(prog, path),array_of_strings[0]);
if (prog[strlen(prog)-1] == '\n') prog[strlen(prog)-1] = '\0';

末尾の改行がある場合はそれを削除し、ファイルのリストは成功しました。

Shell>ls
DEBUG: [/bin/ls]
accounts2011.ods  birthdays    shares    workspace_android
accounts2012.ods  development  wildlife
Shell>_

これは証明のためのデバッグにすぎず、実際のコードには適していないため、解析を修正する必要があります。


バッファオーバーフロー保護を使用してユーザーから入力を取得し、長すぎる場合は入力行の残りをクリーンアップし、プロンプトを表示し、(この場合最も重要な)改行。

于 2012-09-21T01:43:15.690 に答える
2

この線

char* prog = malloc(sizeof(char)*(strlen(array_of_strings[0]+strlen(path))));

間違っているようです。意味がないのですか

char* prog = malloc(sizeof(char)*(strlen(array_of_strings[0])+strlen(path)));

(括弧の移動に注意してください)。(予約しているバイト数)は、パス(連結しようとしている文字列)strlen(array_of_strings[0]+strlen(path))の長さとパスの合計と予測できない関係になります。array_of_strings[0]これにより、セグメンテーション違反が発生している可能性があります。

于 2012-09-21T02:01:08.527 に答える
0

また、execv の後、現在の作業ディレクトリで奇妙なことが起こっています。「Shell>pwd」または「Shell>ls /home/」を試してください。

とにかく、fgets の直後の「buffer」文字列の末尾にある「\n」文字を削除することで解決できたのではないかと思います。それがあなたのために働くかどうか見てください:

 fgets(buffer, 512, stdin);
 int j = strlen(buffer) - 1;
 if (buffer[j] == '\n')
     buffer[j] = 0;

なぜ奇妙なCWD動作が起こったのか、私にはまだ謎です...

お役に立てれば。

于 2012-09-21T02:16:24.560 に答える