EXECVEAT(2) | Linux Programmer's Manual | EXECVEAT(2) |
execveat - ディレクトリファイルディスクリプターからの相対パスで指定されるプログラムを実行する
#include <unistd.h>
int execveat(int dirfd, const char
*pathname,
char *const argv[], char *const envp[],
int flags);
execveat() システムコールは dirfd と pathname の組み合わせで参照されるプログラムを実行する。 execve(2) と全く同様に動作するが、 以下で説明する点が異なる。
pathname で指定されたパス名が相対パスの場合、このパス名はファイルディスクリプター dirfd が参照するディレクトリに対する相対パスと解釈される (execve(2) に相対パス名を渡した場合のように、呼び出したプロセスのカレントワーキングディレクトリに対する相対パスではない)。
pathname で指定されたパス名が相対パスで、 dirfd が特別な値 AT_FDCWD の場合、 (execve(2) と同様に) pathname は呼び出したプロセスのカレントワーキングディレクトリに対する相対パスと解釈される。
pathname で指定されたパス名が絶対パスの場合、 dirfd は無視される。
pathname が空文字列で、 AT_EMPTY_PATH フラグが指定されている場合、 ファイルディスクリプター dirfd は実行するファイルを指定する (すなわち dirfd はディレクトリではなく実行ファイルを参照する)。
flags 引数は、以下に示す値の 0 個以上を指定できるビットマスクである。
成功すると execveat() は返らない。エラーの場合は -1 を返し、 errno を適切に設定する。
execve() で発生するのと同じエラーが execveat() でも起こる。 execveat() では以下のエラーも発生する。
execveat() はバージョン 3.19 で Linux に追加された。 GNU C ライブラリによるサポートは検討中である。
execveat() システムコールは Linux 固有である。
openat(2) で説明されている理由に加え、 execveat() システムコールは、 fexecve(3) を /proc ファイルシステムがマウントされていないシステムで実装するためにも必要である。
スクリプトファイルを実行するように要求された際、 スクリプトインタープリターに渡される argv[0] は、 /dev/fd/N 形式または /dev/fd/N/P 形式の文字列である。 ここで N は dirfd 引数で渡されたファイルディスクリプター数である。 最初の形式の文字列となるのは、 AT_EMPTY_PATH が使用された場合である。 2 番目の形式の文字列になるのは、 スクリプトが dirfd と pathname の両方を使って指定された場合である。 このとき P は pathname に指定された値である。
fexecve(3) で説明されているのと同じ理由で、 execveat() を使う際の理にかなった方法は dirfd に close-on-exec フラグをセットすることである (ただし「バグ」を参照のこと)。
上記で説明したエラー ENOENT は、 以下の形式の呼び出しに渡すファイルディスクリプターで close-on-exec フラグをセットできないことを意味している。
execveat(fd, "", argv, envp, AT_EMPTY_PATH);
しかしながら、 close-on-exec フラグをセットできないということは、 スクリプトを参照するファイルディスクリプターはスクリプト自身に見えてしまうということである。 ファイルディスクリプターを無駄に使うだけでなく、 ファイルディスクリプターが見えてしまうことにより、 スクリプトが execveat() を再帰的に利用する状況ではファイルディスクリプターの枯渇につながる可能性がある。
この man ページは Linux man-pages プロジェクトのリリース 5.10 の一部である。プロジェクトの説明とバグ報告に関する情報は https://www.kernel.org/doc/man-pages/ に書かれている。
2017-09-15 | Linux |