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
|