Bug #16787 » allow-dir.home-for-non-login-procs-v2.patch
| configure.ac | ||
|---|---|---|
|
AC_CHECK_FUNCS(getpgrp)
|
||
|
AC_CHECK_FUNCS(getpriority)
|
||
|
AC_CHECK_FUNCS(getpwnam_r)
|
||
|
AC_CHECK_FUNCS(getpwuid)
|
||
|
AC_CHECK_FUNCS(getpwuid_r)
|
||
|
AC_CHECK_FUNCS(getrandom)
|
||
|
AC_CHECK_FUNCS(getresgid)
|
||
|
AC_CHECK_FUNCS(getresuid)
|
||
| file.c | ||
|---|---|---|
|
#include "ruby/thread.h"
|
||
|
#include "ruby/util.h"
|
||
|
#if defined(HAVE_PWD_H)
|
||
|
# if defined(HAVE_GETPWUID_R)
|
||
|
# define USE_GETPWUID_R 1
|
||
|
# define GETPW_R_SIZE_DEFAULT 0x1000
|
||
|
# define GETPW_R_SIZE_LIMIT 0x10000
|
||
|
# if defined(_SC_GETPW_R_SIZE_MAX)
|
||
|
# define GETPW_R_SIZE_INIT sysconf(_SC_GETPW_R_SIZE_MAX)
|
||
|
# else
|
||
|
# define GETPW_R_SIZE_INIT GETPW_R_SIZE_DEFAULT
|
||
|
# endif
|
||
|
# elif defined(HAVE_GETPWUID)
|
||
|
# define USE_GETPWUID 1
|
||
|
# endif
|
||
|
#endif
|
||
|
VALUE rb_cFile;
|
||
|
VALUE rb_mFileTest;
|
||
|
VALUE rb_cStat;
|
||
| ... | ... | |
|
rb_default_home_dir(VALUE result)
|
||
|
{
|
||
|
const char *dir = getenv("HOME");
|
||
|
if (dir)
|
||
|
return copy_home_path(result, dir);
|
||
|
#if defined HAVE_PWD_H
|
||
|
if (!dir) {
|
||
|
const char *login = getlogin();
|
||
|
if (login) {
|
||
|
struct passwd *pw = getpwnam(login);
|
||
|
if (pw) {
|
||
|
copy_home_path(result, pw->pw_dir);
|
||
|
endpwent();
|
||
|
return result;
|
||
|
}
|
||
|
endpwent();
|
||
|
rb_raise(rb_eArgError, "couldn't find HOME for login `%s' -- expanding `~'",
|
||
|
login);
|
||
|
}
|
||
|
else {
|
||
|
rb_raise(rb_eArgError, "couldn't find login name -- expanding `~'");
|
||
|
#if !defined(USE_GETPWUID_R) && !defined(USE_GETPWUID)
|
||
|
rb_raise(rb_eArgError, "couldn't find HOME environment -- expanding `~'");
|
||
|
#else
|
||
|
/* We'll look up the user's dflt home dir in the password db, by uid */
|
||
|
uid_t ruid = getuid();
|
||
|
struct passwd *pwptr;
|
||
|
# ifdef USE_GETPWUID_R
|
||
|
struct passwd pwd;
|
||
|
char *buf;
|
||
|
long bufsize = GETPW_R_SIZE_INIT; /* maybe -1 */
|
||
|
if (bufsize < 0)
|
||
|
bufsize = GETPW_R_SIZE_DEFAULT;
|
||
|
VALUE getpw_tmp = rb_str_tmp_new(bufsize);
|
||
|
buf = RSTRING_PTR(getpw_tmp);
|
||
|
bufsize = rb_str_capacity(getpw_tmp);
|
||
|
rb_str_set_len(getpw_tmp, bufsize);
|
||
|
int e;
|
||
|
errno = 0;
|
||
|
while ((e = getpwuid_r(ruid, &pwd, buf, bufsize, &pwptr)) != 0) {
|
||
|
if (e != ERANGE || bufsize >= GETPW_R_SIZE_LIMIT) {
|
||
|
rb_str_resize(getpw_tmp, 0);
|
||
|
rb_syserr_fail(e, "getpwuid_r");
|
||
|
}
|
||
|
rb_str_modify_expand(getpw_tmp, bufsize);
|
||
|
buf = RSTRING_PTR(getpw_tmp);
|
||
|
bufsize = rb_str_capacity(getpw_tmp);
|
||
|
}
|
||
|
#endif
|
||
|
if (!dir) {
|
||
|
rb_raise(rb_eArgError, "couldn't find HOME environment -- expanding `~'");
|
||
|
if (pwptr == NULL) {
|
||
|
/* no record in the password database for the uid */
|
||
|
rb_str_resize(getpw_tmp, 0);
|
||
|
rb_raise(rb_eArgError, "getpwuid_r couldn't find HOME for uid `%ld' -- expanding `~'",
|
||
|
(long)ruid);
|
||
|
}
|
||
|
copy_home_path(result, pwptr->pw_dir);
|
||
|
rb_str_resize(getpw_tmp, 0);
|
||
|
# elif defined(USE_GETPWUID)
|
||
|
errno = 0;
|
||
|
pwptr = getpwuid(ruid);
|
||
|
if (pwptr == NULL) {
|
||
|
if (errno) {
|
||
|
rb_syserr_fail(errno, "getpwuid");
|
||
|
}
|
||
|
rb_raise(rb_eArgError, "getpwuid couldn't find HOME for uid `%ld' -- expanding `~'",
|
||
|
(long)ruid);
|
||
|
}
|
||
|
return copy_home_path(result, dir);
|
||
|
|
||
|
copy_home_path(result, pwptr->pw_dir);
|
||
|
# else
|
||
|
# error Hello! Ruby developers believe this message must not happen.
|
||
|
# error BUG: Either USE_GETPWUID_R or USE_GETPWUID should be defined here.
|
||
|
# error If you encounter this message, can you file a bug report?
|
||
|
# error Remember to attach a detailed description of your environment.
|
||
|
# error Thank you!
|
||
|
# endif
|
||
|
return result;
|
||
|
#endif /* !defined(USE_GETPWUID_R) && !defined(USE_GETPWUID) */
|
||
|
}
|
||
|
static VALUE
|
||