EXECVE(2)

名称
execve - ファイルを実行する

ライブラリ
libc

書式
#include <unistd.h> int execve(const char *path, char *const argv[], char *const envp[])

解説
execve() は呼び出しプロセスを新しいプロセスに変換します。新しいプロセスは new process file と呼ばれる通常のファイルに基いて構成されます。このファイルの名前は path によって指定されます。 このファイルは実行可能オブジェクトファイル、またはインタプリタ用の データのファイルです。実行可能オブジェクトファイルは、識別ヘッダに データのページが続いたもので構成されます。このデータは 初期プログラム (テキスト) と初期値ありデータのページを表します。 追加のページはヘッダの指定によって 0 データで初期化される場合があります。 elf(5) および a.out(5) を参照してください。

インタプリタファイルは次の形式の行で開始します。

#! interpreter [arg]

インタプリタファイルが execve されるとき、システムは実際には指定の interpreter を execve します。オプションの arg が指定されている場合、それは interpreter の 1番目の引数に なり、元々の execve で指定されたファイルの名前は 2 番目の引数になります。それ以外では execve で指定されたファイルの名前が 1番目の引数になります。 元々の引数はシフトされて後続の引数に なります。0 番目の引数は指定された interpreter に設定されます。

引数 argv は、ヌルで終了する文字ポインタの配列を指すポインタです。 各文字ポインタはヌル文字で終了する文字列を指します。 これらの文字列は、新しいプロセスから参照できる引数リストを構成します。 少なくとも 1 つの引数が配列内に存在している必要があります。 慣習では、最初の要素が実行されたプログラムの名前になるはずです (たとえば、 path の最後の構成要素)。

引数 envp も、ヌルで終了する文字ポインタの配列を指すポインタです。 各文字ポインタはヌル文字で終了する文字列を指します。 この配列を指すポインタは、通常、グローバル変数 environ に保存されます。これらの文字列は、引数としてコマンドへ直接 渡されない情報を新しいプロセスに渡します (environ(7) を参照)。

呼び出しプロセスイメージ内でオープンされているファイル記述子は、 新しいプロセスイメージの中でもオープンされたままです。 しかし、close-on-exec フラグが設定されているものは例外です。 (close(2) と fcntl(2) を参照)。 オープンされたままの記述子は execve() の影響を受けません。

呼び出しプロセスで無視するように設定されたシグナルは、 新しいプロセス内でも無視されるように設定されます。 呼び出しプロセスイメージ内で捕捉されるように設定されたシグナルは、 新しいプロセスイメージ内でデフォルトのアクションに 設定されます。ブロックされたシグナルは、 シグナルアクションの変化とは無関係にブロックされたままになります。 シグナルスタックは未定義にリセットされます (詳細については sigaction(2) を参照してください)。

新しいプロセスイメージファイルに set-user-ID モードビット が設定されている場合 (chmod(2) を参照)、新しいプロセスイメージの実効ユーザ ID は、 新しいプロセスイメージファイルの所有者 ID に設定されます。 新しいプロセスイメージファイルに set-group-ID モードビットが 設定されている場合、新しいプロセスイメージの実効グループ ID は新しい プロセスイメージファイルのグループ ID に設定されます (実効グループ ID はグループリストの最初の要素です)。 新しいプロセスの実ユーザ ID、実グループ ID、およびその他の グループ ID は、呼び出しプロセスイメージと同じになります。 set-user-ID および set-group-ID 処理の後、実効ユーザ ID は saved set-user-ID として記録され、実効グループ ID は saved set-group-ID として記録されます。 これらの値は、後で実効 ID を変更するのに使用できます (setuid(2) を参照)。

該当するファイルシステムで nosuid オプションが有効な場合、または新しいプロセスファイルがインタプリタ ファイルの場合、set-ID ビットは意味を持ちません。 実効 ID が変更された場合、システムコールのトレースは 無効になります。

また、新しいプロセスは呼び出しプロセスから次の属性を継承します。

プロセス ID | getpid(2)  を参照
親プロセス ID | getppid(2)  を参照
プロセスグループ ID | getpgrp(2)  を参照
アクセスグループ | getgroups(2)  を参照
作業ディレクトリ | chdir(2)  を参照
ルートディレクトリ | chroot(2)  を参照
制御端末 | termios(4)  を参照
リソースの使用状況 | getrusage(2)  を参照
インターバルタイマ | getitimer(2)  を参照
リソースの使用制限 | getrlimit(2)  を参照
ファイルモードマスク | umask(2)  を参照
シグナルマスク | sigvec(2),
sigsetmask(2) を参照

execve() 呼び出しの結果として実行されるとき、プログラムは次のように呼び出されます。

    main(argc, argv, envp)
    int argc;
    char **argv, **envp;

ここで、 argc は argv の要素数 (``arg count'') であり、 argv は、引数自身を指す文字ポインタの配列を指します。

戻り値
execve() は現在のプロセスイメージを新しいプロセスイメージで上書きするので、 処理が成功した呼び出しには戻るプロセスがありません。 execve() が呼び出しプロセスに返ってくる場合は エラーが起きています。戻り値は -1 で、 エラーを示すためにグローバル変数 errno が設定されます

エラー
次の場合、 execve() は処理に失敗し、呼び出しプロセスに戻ります。

[ENOTDIR]
    パスの構成要素中にディレクトリ以外のものが含まれています。

[ENAMETOOLONG]
    パス名の構成要素が 255 文字を越えているか、 またはパス名全体が 1023 文字を越えています。

[ENAMETOOLONG]
    インタプリトされるスクリプトを起動するときに、 インタプリタの名前が MAXSHELLCMDLEN 文字を越えています。

[ENOENT]
    新しいプロセスファイルが存在しません。

[ELOOP]
    パス名を変換するときに検出されたシンボリックリンクが多すぎます。

[EACCES]
    指定されたパスには、検索が許可されていないディレクトリが含まれています

[EACCES]
    新しいプロセスファイルが通常のファイルではありません。

[EACCES]
    新しいプロセスファイルは、実行が許可されていません。

[ENOEXEC]
    新しいプロセスファイルに適切なアクセス許可がありますが、 ヘッダのマジック番号が無効です。

[ETXTBSY]
    新しいプロセスファイルは純粋な手続き (共有テキスト) ファイルで、 現時点で他のプロセスによって書込みまたは読取り用にオープンされています。

[ENOMEM]
    新しいプロセスは、許された (getrlimit(2) で課された最大値) 以上の仮想メモリを必要とします。

[E2BIG]
    新しいプロセスの引数リストのバイト数がシステムの課した上限を 越えています。この上限は、 sysctl(3) の MIB 変数 KERN_ARGMAX により指定されます。

[EFAULT]
    新しいプロセスファイルは、ヘッダ内のサイズ値で 示されるほど長くはありません。

[EFAULT]
    path, argv, または envp が正しくないアドレスを指しています。

[EIO]
    ファイルシステムから読取る間に入出力エラーが発生しました。

警告
スーパユーザでないものに対して setuid されたプログラムが、実 uid が ``root'' の時に実行された場合、プログラムは部分的に スーパユーザの権限を持ちます。

関連項目
ktrace(1), fork(2), _exit(2), execl(3), exit(3), sysctl(3), a.out(5), elf(5), environ(7), mount(8)

歴史
execve() 関数は 4.2BSD で登場しました。