8

ユーザーが入力した引数を に渡そうとしていますexecvp()

これまで、文字列を分割しました。ユーザーがを入力すると、"ls" および "-a" の後に NULL 文字が続く形式ls -aで保存されます。tempでこれを適切に指す方法がよくわかりませんexecvp。例では、 を使用して見ましたexecvp(temp[position], temp)。現時点でやろうとしている方法が間違っていることはわかっていますが、適切に行う方法がわかりません! 現時点では、セグメンテーション違反が発生しています。

int main(int argc, char *argv[]) 
{
    char line[124];
    int size = 124;
    char *temp = NULL;

    while(fgets(line, size, stdin) != NULL ) {
        if (strcmp(line, "exit\n") == 0) {
            exit(EXIT_SUCCESS);
        }
        temp = strtok(line, " ");
        while (temp != NULL) {
            printf("%s\n", temp);
            temp = strtok(NULL, " ");
        }
        execvp(temp, &temp);    
    }
    return EXIT_SUCCESS;
}
4

3 に答える 3

7

あなたの問題は、それtempが単一のポインターであり、ポインターの配列をに渡す必要があることですexecvp()

何かのようなもの:

    enum { MAX_ARGS = 64 };
    char *args[MAX_ARGS];
    char **next = args;

    temp = strtok(line, " ");
    while (temp != NULL)
    {
        *next++ = temp;
        printf("%s\n", temp);
        temp = strtok(NULL, " ");
    }
    *next = NULL;
    execvp(args[0], args);

argv[argc] == NULLのように、引数リストにはターミネータとして null ポインタが与えられていることに注意してくださいmain()。明らかに、エラー チェックを怠っています (63 個を超える引数を渡すと、args配列がオーバーフローすることになります)。しかし、これには核となる考えが含まれています。


この例では、単純なコマンドがls機能しないようです。試してみたところmkdirechoうまく機能しているようです。を渡すlsと、 から -1 が返されexecvp()ます。

問題が何であるかはわかりません—これらはすべて私にとってはうまくいきます:

  • ls
  • ls -l
  • ls -l madump.c(madump.cたまたま、テストしているディレクトリ内のファイルです)

私が使用したコードは次のとおりです。

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

int main(void) 
{
    char line[1024];

    while (fgets(line, sizeof(line), stdin) != NULL)
    {
        if (strcmp(line, "exit\n") == 0)
            exit(EXIT_SUCCESS);

        char *args[64];
        char **next = args;
        char *temp = strtok(line, " \n");
        while (temp != NULL)
        {
            *next++ = temp;
            printf("%s\n", temp);
            temp = strtok(NULL, " \n");
        }
        *next = NULL;

        puts("Checking:");
        for (next = args; *next != 0; next++)
            puts(*next);

        execvp(args[0], args);
    }

    return EXIT_SUCCESS;
}

名前の最後に改行を含むディレクトリを作成した後、トークンリストに追加\nしたことに注意してください。strtok()友人を困らせたり、半学歴の敵を困惑させるのには適していますが、他のほとんどの観点からは迷惑です. execvp()実際に渡す直前に、渡されるデータをどのように出力するかに注意してください。多くの場合、引数の開始位置と終了位置を明確に示すために、printf("<<%s>>\n", *next);代わりに を使用します。puts()

コマンドの実行による出力 ( doit) は次のとおりです。

$ ./doit
ls -l madump.c
ls
-l
madump.c
Checking:
ls
-l
madump.c
-rw-r--r--  1 jleffler  staff  2352 Jul 28  2011 madump.c
$

あなたのバージョンから何を得ましたか?

于 2013-03-21T05:04:20.893 に答える
3

あなたのコードが現在見えるように、あなたのwhile(temp != NULL)終了後、 tempNULLになります!

execvp最初の引数は、新しいプロセスイメージとなるファイルのパスであると想定しています。2番目の引数は、NULLで終了する文字列の配列であると想定されます。この場合、その配列の最後のメンバーはNULLポインターであり、最初のメンバーは最初の引数で指定されたファイルのファイル名です。

これをコードに実装するには、while代わりに次のループを検討してください。

char **argList = NULL;
unsigned int numArgs = 0;
while (temp != NULL) {
    numArgs++;

    /* Reallocate space for your argument list */
    argList = realloc(argList, numArgs * sizeof(*argList));

    /* Copy the current argument */
    argList[numArgs - 1] = malloc(strlen(temp) + 1, 1); /* The +1 for length is for the terminating '\0' character */
    snprintf(argList[numArgs - 1], strlen(temp) + 1, "%s", temp);

    printf("%s\n", temp);
    temp = strtok(NULL, " ");
}

/* Store the last NULL pointer */
numArgs++;
argList = realloc(argList, numArgs * sizeof(*argList));
argList[numArgs - 1] = NULL;

/* Finally, pass this to execvp */
execvp(argList[0], argList);
/* If you reach here, execvp() failed */

上記で提供したコードは、エラーチェック(いつreallocまたはmalloc失敗したかなど)を行いませんが、基本的に次の点に注意してください。

  1. 引数1:メモリに配置されるファイルのパス名。
  2. 引数2:そのリストの最初のメンバー=ファイル名、最後のメンバー=NULLポインターである引数のリスト。

より明確で非常に単純な例については、ドキュメントを参照してください。

于 2013-03-21T04:57:08.023 に答える
1

セグメンテーション違反は、execvpにNULLポインターを渡しているためだと思います。呼び出しのすぐ上のループはこれを保証します。

あなたがやろうとしていることをするために、あなたはあなたが現在呼んでいるもののために文字列ポインタの配列を作成する必要があるでしょうtemp。これは、argv呼び出すプログラムの配列になります。そのため、コマンドは通常、プログラムの名前であるとして使用されexecvp (temp[0], temp)ますargv[0]

したがって、文字列ポインタの配列を作成してみて、それぞれがからのトークン化された単語を指すようにしlineます。mallocを使用する必要があるかもしれませんが、賢くなりたい場合は、を直接指すことができるかもしれませんline。その場合は、すべての「単語」の直後の文字をに設定する必要があります\0

于 2013-03-21T04:56:44.490 に答える