system(3) シェルコマンドの実行

書式

#include <stdlib.h>


int system(const char *command);

説明

system() は command で指定したコマンドを /bin/sh -c command の形で実行する。指定したコマンドが終了すればこの関数も終了する。 コマンド実行中は、 SIGCHLD はブロックされ、 SIGINTSIGQUIT は無視される。

返り値

エラーが発生した場合 (fork(2) に失敗した場合など)、-1 を返す。 そうでなければ、コマンドのステータスを返す。 後者の場合、ステータスは wait(2) で定義されているフォーマットで返ってくる。 従って、コマンドの終了コードは WEXITSTATUS(status) で得ることが出来る。 /bin/sh が実行出来なかった場合、 終了ステータスはコマンドが exit(127) を実行した場合と同じになる。

command の値が NULL のときは、 system() はシェルが利用可能ならゼロ以外の値を返し、利用不可ならゼロを返す。

system() は他の子プロセスのウエイトステータスには影響を与えない。

準拠

C89, C99, POSIX.1-2001.

注意

(「どの」ヘッダファイルをインクルードするよりも前に) 機能検査マクロ _XOPEN_SOURCE が定義された場合には、 wait(2) で説明されているマクロ群 (WEXITSTATUS() 等) が <stdlib.h> をインクルードすると利用可能になる。

既に述べたように、 system() は SIGINTSIGQUIT を無視する。 よってループから system() を呼ぶプログラムは、 以下の例のように子プロセスの終了状態を自分でチェックしておかないと、 中断できなくなるかもしれない。

    while (something) {
        int ret = system("foo");
        if (WIFSIGNALED(ret) &&
            (WTERMSIG(ret) == SIGINT || WTERMSIG(ret) == SIGQUIT))
                break;
    }

set-user-ID や set-group-ID の特権をもつプログラムの中では system() を使ってはいけない。なぜなら、ある環境変数の未知の値によって システムの安全が損なわれるからである。代わりに exec(3) 関連の関数群の中で execlp(3) と execvp(3) 以外の関数を使用すべきである。 実際のところ、 system() は /bin/sh が bash バージョン 2 であるシステムでは、 set-user-ID や set-group-ID の特権を持つプログラムからは正しく動作しない。 なぜなら、bash バージョン 2 はスタートアップ時に特権を落とすからである。 (Debian では、sh として起動された時にはこのような動作を行なわないように 修正された bash を用いている)

glibc 2.1.3 より前のバージョンでは、 command が NULL の場合に /bin/sh が利用可能かどうかのチェックは実際には行わず、 いつでも利用可能であるとみなしていた。 system() はこの場合に常に 1 を返していた。 POSIX.1-2001 ではシェルが提供されているという標準に準拠した実装を 要求しているが、glibc 2.1.3 以降ではシェルのチェックを実行している。 なぜなら、呼び出し元のプログラムが system() を呼び出すより前に (POSIX.1-2001 では規定されていない) chroot(2) を呼び出していた時には、シェルが利用可能でない場合や実行可能ファイル でない場合があるからである。

実行したシェルコマンドが 127 (/bin/sh の呼び出しに失敗した時に返す値) を返すことも考えられる。 そのため、プログラムは (リターンコードを見るだけでは) execve(2) の呼び出しが失敗したことを確実に知ることはできない。

この文書について

この man ページは Linux man-pages プロジェクトのリリース 3.65 の一部 である。プロジェクトの説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。