1

Linux シェルを構築していますが、現在の頭痛の種は、コマンド ライン引数を fork/exec されたプログラムとシステム関数に渡すことです。

現在、すべての入力は、グローバル変数 char * parsed_arguments 内のスペースと改行でトークン化されています。たとえば、入力ディレクトリ /usa/folderbは次のようにトークン化されます。

parsed_arguments[0] = dir
parsed_arguments[1] = /usa/folderb

parsed_arguments はすべてを完全にトークン化します。私の問題は、シェルで実行するコマンド/最初の引数/実行可能ファイルへのパスを除外するparsed_argumentsのサブセットのみを取得し、それらをpassed_argumentsと呼ばれる新しい配列に保存することです。

前の例ではdir /usa/folderb

parsed_arguments[0] = dir
parsed_arguments[1] = /usa/folderb

passed_arguments[0] = /usa/folderb
passed_arguments[1] = etc....

現在、私はこれで運が悪いので、誰かが私を助けてくれることを願っています. ここに私がこれまでに取り組んできたことのいくつかのコードがあります:

引数をコピーしようとしている方法:

void  command_Line()
{

  int i = 1;
  for(i;parsed_arguments[i]!=NULL;i++)
    printf("%s",parsed_arguments[i]);

}

コマンドを読み取る関数:

void readCommand(char newcommand[]){

printf("readCommand: %s\n", newcommand);


//parsed_arguments =  (char* malloc(MAX_ARGS));
//  strcpy(newcommand,inputstring);
  parsed =  parsed_arguments;
  *parsed++ = strtok(newcommand,SEPARATORS);   // tokenize input
    while ((*parsed++ = strtok(NULL,SEPARATORS)))
      //printf("test1\n"); // last entry will be NULL

      //passed_arguments=parsed_arguments[1];

    if(parsed[0]){  
      char *initial_command =parsed[0];

  parsed= parsed_arguments;
  while (*parsed) fprintf(stdout,"%s\n ",*parsed++);
  // free (parsed);
  // free(parsed_arguments);

    }//end of if


  command_Line();

}//end of ReadCommand

分岐機能:

else if(strstr(parsed_arguments[0],"./")!=NULL)
    {
      int pid;
      switch(pid=fork()){
      case -1:
       printf("Fork error, aborting\n");
       abort();
      case 0:
        execv(parsed_arguments[0],passed_arguments);

      }

    }

ここに画像の説明を入力

これは私のシェルが現在出力しているものです。初めて実行すると、必要なものに近いものが出力されますが、その後のすべての呼び出しでプログラムが壊れます。さらに、追加の呼び出しごとに、解析された引数が出力に追加されます。

これは、元のシェルが生成するものです。繰り返しますが、それは私が望むものに近いですが、完全ではありません. コマンド (つまり、"./testline") を省略したい。

4

1 に答える 1

1

あなたのtestlineプログラムは、あなたのツールボックスに入れるのに賢明なものです。al引数を 1 行に 1 つずつ出力する (Argument List 用に) 呼び出す同様のプログラムがあります。ただし、印刷されませんargv[0](と呼ばれることはわかっていますal)。testlineスキップも簡単にアレンジできますargv[0]。Unix の規則では、これargv[0]がプログラムの名前であることに注意してください。それを変更しようとすべきではありません (システム全体と戦うことになります)。

#include <stdio.h>

int main(int argc, char **argv)
{
    while (*++argv != 0)
        puts(*argv);
    return 0;
}

あなたの関数command_line()は、グローバル変数に不必要に依存することを除けば、合理的です。グローバル変数は悪臭 (H 2 S など) と考えてください。できる限り避けてください。それはもっと似ているはずです:

void command_Line(char *argv[])
{
    for (int i = 1; argv[i] != NULL; i++)
        printf("<<%s>>\n", argv[i]);
}

C89 に行き詰まっている場合はint i;、ループの外側で宣言for (i = 1; ...)し、ループ コントロールでのみ使用する必要があります。ここでの印刷では、各引数を 1 行で区切り、マーカー文字 (<<および>>— 気まぐれや偏見に合わせて変更してください) で囲んでいることに注意してください。ループ内の改行をスキップして (代わりにスペースを使用することもできます)、ループの後に改行を追加しても問題ありません ( putchar('\n');)。これにより、より優れた、より汎用に近いデバッグ ルーチンが作成されます。(「ダンプ」関数を作成するときは、通常、void dump_argv(FILE *fp, const char *tag, char *argv[])標準エラーまたは標準出力に出力できるように使用し、ダンプが書き込まれた場所を識別するタグ文字列を含めます。)

残念ながら、あなたのreadCommand()機能の断片的な性質を考えると、それを首尾一貫して批判することはできません. コメントアウトされた行は懸念を引き起こすのに十分ですが、実行している実際のコードがなければ、どのような問題や間違いを犯しているのかを推測することはできません. 示されているように、これは次と同等です。

void readCommand(char newcommand[])
{
    printf("readCommand: %s\n", newcommand);

    parsed = parsed_arguments;
    *parsed++ = strtok(newcommand, SEPARATORS);
    while ((*parsed++ = strtok(NULL, SEPARATORS)) != 0)
    {
        if (parsed[0])
        {
            char *initial_command = parsed[0];
            parsed = parsed_arguments;
            while (*parsed)
                fprintf(stdout, "%s\n ", *parsed++);
        }
    }

    command_Line();
}

変数parsedparsed_argumentsは両方ともグローバルであり、変数initial_commandは設定されていますが使用されていません (別名「無意味」)。if (parsed[0])テストは安全ではありません。前の行でポインターをインクリメントしたため、不確定なメモリを指しています。

表面的には、スクリーン ショットから判断すると、2 回目の使用でparsed_arguments[]および/またはpassed_arguments[]配列を正しくリセットしていません。ゼロに設定されていないインデックスである可能性があります。データがどのように割り当てられているかを知らなければ、何が間違っているのかを知ることは困難です。

この質問を閉じて、システムに戻り、最小限の SSCCE を作成することをお勧めします。約 100 行未満にする必要があります。execv()(または) を実行する必要はありませんが、上記の関数fork()の変形を使用して実行するコマンドを出力する必要があります。command_Line()この回答でこの質問を削除 (閉じる) できない場合は、SSCCE コードで編集し、この回答へのコメントで私に通知してください。

于 2013-04-20T02:09:49.910 に答える