C言語の基礎 - 外部コマンド
ナビゲーションに移動
検索に移動
概要
異なるプロセスを生成して外部コマンドプログラムを実行する場合、system
関数 (シェルの機能を使用してコマンドを実行) およびexec
関数ファミリーを使用する。
他にも、popen
関数 (パイプで通信可能) 等がある。
ただし、これらの関数を実行する時、制御はそのプログラムへ移行するため自身のプログラムには戻らない。 (実行に失敗した場合だけ戻る)
そのため、処理を続行する場合は、fork
関数と組み合わせて使用する必要がある。
system関数
system
関数はセキュリティ上の懸念があり、外部からの入力を直接実行することにより、悪意のあるコマンドインジェクション攻撃に対する脆弱性を持つ。
特に、外部からの入力を含む場合、その入力が信頼できるかどうかを確認する。
#include <stdio.h>
#include <stdlib.h>
int main()
{
// lsコマンドを実行する
int result = system("ls non_existent_directory");
if (result != 0) {
fprintf(stderr, "Command execution failed with error code: %d", result);
}
else {
fprintf(stdout, "Command executed successfully");
}
return 0;
}
exec関数ファミリー
exec関数ファミリーとは
system
関数の代わりに、外部コマンドを実行するためのより安全な方法がexecl
関数およびexecv
関数である。
exec
関数ファミリーは、現在のプロセスを指定したプログラムに置き換えて実行する。
そのため呼び出し元へ制御が戻ることはない。
関数に渡される第1引数は実行されるプログラムのパスである。
第2引数以降は、その実行されるプログラムのパスへ引数を指定する。
第2引数において、execl
関数は可変長の引数、execv
関数は引数として配列が渡す。
また、exec
関数ファミリーの最後の引数はNULL
またはnullptr
にする必要があり、(char*)NULL
または(char*)nullptr
とすべきである。
戻り値
エラーが起きた場合のみ呼び出し元に-1
を返す。
それ以外の場合は復帰せず、戻り値も存在しない。
execl関数の使用例
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
int main()
{
// lsコマンドを実行する
execl("/bin/ls", "ls", "-l", (char*)nullptr);
if(errno != 0) {
// エラーが発生した場合
perror("exec");
}
return 0;
}
execv関数の使用例
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
int main()
{
const char *str[] = {"/bin/echo", "hoge", "piyo", NULL};
// echoコマンドを実行する
execv("/bin/echo", str);
if(errno != 0) {
// エラーが発生した場合
perror(strerror(errno));
}
return 0;
}