#include <sys/types.h> #include <pwd.h> struct passwd *getpwnam(const char *name); struct passwd *getpwuid(uid_t uid); int getpwnam_r(const char *name, struct passwd *pwd, char *buf, size_t buflen, struct passwd **result); int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf, size_t buflen, struct passwd **result);
glibc 向けの機能検査マクロの要件 (feature_test_macros(7) 参照):
getpwnam_r(), getpwuid_r():
getpwuid() 関数は、ユーザー ID uid にマッチするパスワードデータベースのエントリーを 要素毎に分解し、各要素を格納した構造体へのポインターを返す。
passwd 構造体は、<pwd.h> で以下のように定義されている:
struct passwd {
char *pw_name; /* ユーザー名 */
char *pw_passwd; /* ユーザーのパスワード */
uid_t pw_uid; /* ユーザー ID */
gid_t pw_gid; /* グループ ID */
char *pw_gecos; /* ユーザー情報 */
char *pw_dir; /* ホームディレクトリ */
char *pw_shell; /* シェルプログラム */
};
これらのフィールドの詳しい情報については passwd(5) を参照のこと。
getpwnam_r() と getpwuid_r() 関数は、それぞれgetpwnam() と getpwuid() と同じ情報を取得するが、取得した passwd 構造体を pwd が指す領域に格納する。passwd 構造体のメンバーが指す文字列は、 サイズ buflen のバッファー buf に格納される。成功した場合 *result には結果へのポインターが格納される。エントリーが見つからなかった 場合やエラーが発生した場合には *result には NULL が入る。
呼び出し
sysconf(_SC_GETPW_R_SIZE_MAX)
は、 errno を変更せずに -1 を返すか、 buf の初期サイズの推奨値を 返す。(このサイズが小さすぎる場合、呼び出しは ERANGE で失敗し、この 場合には呼び出し側はバッファーを大きくしてから再度呼び出すことができる。)
返り値は静的な領域を指しており、その後の getpwent(3), getpwnam(), getpwuid() の呼び出しで上書きされるかもしれない。 (返されたポインターを free(3) に渡さないこと。)
成功すると、 getpwnam_r() と getpwuid_r() は 0 を返し、 *result に pwd を設定する。 マッチするパスワードエントリーが見つからなかった場合には、 0 を返し、 *result に NULL を設定する。 エラーの場合、エラー番号を返し、 *result に NULL を設定する。
インターフェース | 属性 | 値 |
getpwnam() | Thread safety | MT-Unsafe race:pwnam locale |
getpwuid() | Thread safety | MT-Unsafe race:pwuid locale |
getpwnam_r(),
getpwuid_r() | Thread safety | MT-Safe locale |
フィールド pw_dir には、ユーザーの作業ディレクトリ名の初期値が格納される。 ログインプロセスは、このフィールドの値を使って、 ログインシェルの HOME 環境変数を初期化する。 アプリケーションが、ユーザーのホームディレクトリを決定する場合には、 (getpwuid(getuid())->pw_dir の値ではなく) HOME の値を検査するようにすべきである。 なぜなら、このようにすることで、ユーザーがログインセッション中で 「ホームディレクトリ」の意味を変更できるようになるからである。 別のユーザーのホームディレクトリ (の初期値) を知るには getpwnam("username")->pw_dir か同様の方法を使う必要がある。
#include <pwd.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h>
int
main(int argc, char *argv[])
{
struct passwd pwd;
struct passwd *result;
char *buf;
size_t bufsize;
int s;
if (argc != 2) {
fprintf(stderr, "Usage: %s username\n", argv[0]);
exit(EXIT_FAILURE);
}
bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
if (bufsize == -1) /* 値を決定できなかった */
bufsize = 16384; /* 十分大きな値にすべき */
buf = malloc(bufsize);
if (buf == NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}
s = getpwnam_r(argv[1], &pwd, buf, bufsize, &result);
if (result == NULL) {
if (s == 0)
printf("Not found\n");
else {
errno = s;
perror("getpwnam_r");
}
exit(EXIT_FAILURE);
}
printf("Name: %s; UID: %jd\n", pwd.pw_gecos,
(intmax_t) pwd.pw_uid);
exit(EXIT_SUCCESS);
}