を呼び出す必要がある場合execvp()
は、これらの文字列を実行可能ファイル名と引数の配列に分割する必要があります(最初はプログラムの「名前」で、最後はNULLポインターです)。
つまり、次のような意味です。
char cmd1[] = "ls"; char *args1[] = {"ls", "-l", NULL};
char cmd1[] = "rm"; char *args1[] = {"rm", "*.txt", NULL}; // but see
// globbing below.
char cmd1[] = "cat"; char *args1[] = {"cat", "makefile", NULL};
これは、特に引用、グロブ、エスケープなどを許可したい場合は、重要な演習です。
引用するということは、次のようなコマンドに注意する必要があることを意味します。
rm "file with spaces.txt"
スペースを単純に分割することはできません。コマンド内の項目は、シェルとほぼ同じように解釈する必要があります。スペースを単純に分割すると、正しい文字列ではなく、上記の文字列に対して3つの引数を持つコマンドが得られます。
*.txt
グロブとは、通常、これらの引数を拡張するシェルであるため、ほぼ確実に次のような問題が発生することを意味します。これを直接に渡すと、現在のディレクトリ内のすべてのテキストファイルに一致する多くの引数ではなく、文字通りexecvp()
の単一の引数になります。*.txt
引用とは、次のような処理を行う必要があることを意味します。
ls -l "file with spaces and \" quote in it"
これにより、パーサーがさらに複雑になります。
誤解しないでください、それは可能ですが、それを使用するだけでおそらく気の利いた光景ですsystem()
。
あなたがまだexecvp()
ルートに行くことを考えているなら、あなたはしなければならないでしょう:
- 文字列を別々のトークンに分割します(引用符とエスケープを処理する必要があるため、かなり難しいです)。
- すべての引数をグロブします。つまり、ワイルドカードが含まれている引数(および引用符で囲まれているためにエスケープまたは保護されていない引数のみ)は、複数の引数に展開されます。
- コマンドを先頭に、NULLを末尾に指定して、引数配列を作成します。
execvp()
その配列の最初の要素であるパラメータと配列のアドレスを使用して呼び出します。