Refactor getlogin and getpw* functions

- Extract functions to check not-found conditions
- Set the length to the result of `rb_getlogin`
- Reentrant versions return an error numeber but not `errno`
- Check maybe-undefined macros with `defined`
This commit is contained in:
Nobuyoshi Nakada 2024-09-04 11:44:12 +09:00 committed by Nobuyoshi Nakada
parent 630bfd36f9
commit 08e142b209
Notes: git 2024-09-05 07:56:12 +00:00

102
process.c
View File

@ -5700,6 +5700,12 @@ check_gid_switch(void)
#if defined(HAVE_PWD_H) #if defined(HAVE_PWD_H)
static inline bool
login_not_found(int err)
{
return (err == ENOTTY || err == ENXIO || err == ENOENT);
}
/** /**
* Best-effort attempt to obtain the name of the login user, if any, * Best-effort attempt to obtain the name of the login user, if any,
* associated with the process. Processes not descended from login(1) (or * associated with the process. Processes not descended from login(1) (or
@ -5708,18 +5714,18 @@ check_gid_switch(void)
VALUE VALUE
rb_getlogin(void) rb_getlogin(void)
{ {
#if ( !defined(USE_GETLOGIN_R) && !defined(USE_GETLOGIN) ) # if !defined(USE_GETLOGIN_R) && !defined(USE_GETLOGIN)
return Qnil; return Qnil;
#else # else
char MAYBE_UNUSED(*login) = NULL; char MAYBE_UNUSED(*login) = NULL;
# ifdef USE_GETLOGIN_R # ifdef USE_GETLOGIN_R
#if defined(__FreeBSD__) # if defined(__FreeBSD__)
typedef int getlogin_r_size_t; typedef int getlogin_r_size_t;
#else # else
typedef size_t getlogin_r_size_t; typedef size_t getlogin_r_size_t;
#endif # endif
long loginsize = GETLOGIN_R_SIZE_INIT; /* maybe -1 */ long loginsize = GETLOGIN_R_SIZE_INIT; /* maybe -1 */
@ -5733,10 +5739,8 @@ rb_getlogin(void)
rb_str_set_len(maybe_result, loginsize); rb_str_set_len(maybe_result, loginsize);
int gle; int gle;
errno = 0;
while ((gle = getlogin_r(login, (getlogin_r_size_t)loginsize)) != 0) { while ((gle = getlogin_r(login, (getlogin_r_size_t)loginsize)) != 0) {
if (login_not_found(gle)) {
if (gle == ENOTTY || gle == ENXIO || gle == ENOENT) {
rb_str_resize(maybe_result, 0); rb_str_resize(maybe_result, 0);
return Qnil; return Qnil;
} }
@ -5756,17 +5760,19 @@ rb_getlogin(void)
return Qnil; return Qnil;
} }
rb_str_set_len(maybe_result, strlen(login));
return maybe_result; return maybe_result;
# elif USE_GETLOGIN # elif defined(USE_GETLOGIN)
errno = 0; errno = 0;
login = getlogin(); login = getlogin();
if (errno) { int err = errno;
if (errno == ENOTTY || errno == ENXIO || errno == ENOENT) { if (err) {
if (login_not_found(err)) {
return Qnil; return Qnil;
} }
rb_syserr_fail(errno, "getlogin"); rb_syserr_fail(err, "getlogin");
} }
return login ? rb_str_new_cstr(login) : Qnil; return login ? rb_str_new_cstr(login) : Qnil;
@ -5775,10 +5781,26 @@ rb_getlogin(void)
#endif #endif
} }
/* avoid treating as errors errno values that indicate "not found" */
static inline bool
pwd_not_found(int err)
{
switch (err) {
case 0:
case ENOENT:
case ESRCH:
case EBADF:
case EPERM:
return true;
default:
return false;
}
}
VALUE VALUE
rb_getpwdirnam_for_login(VALUE login_name) rb_getpwdirnam_for_login(VALUE login_name)
{ {
#if ( !defined(USE_GETPWNAM_R) && !defined(USE_GETPWNAM) ) #if !defined(USE_GETPWNAM_R) && !defined(USE_GETPWNAM)
return Qnil; return Qnil;
#else #else
@ -5787,7 +5809,7 @@ rb_getpwdirnam_for_login(VALUE login_name)
return Qnil; return Qnil;
} }
char *login = RSTRING_PTR(login_name); const char *login = RSTRING_PTR(login_name);
struct passwd *pwptr; struct passwd *pwptr;
@ -5807,11 +5829,8 @@ rb_getpwdirnam_for_login(VALUE login_name)
rb_str_set_len(getpwnm_tmp, bufsizenm); rb_str_set_len(getpwnm_tmp, bufsizenm);
int enm; int enm;
errno = 0;
while ((enm = getpwnam_r(login, &pwdnm, bufnm, bufsizenm, &pwptr)) != 0) { while ((enm = getpwnam_r(login, &pwdnm, bufnm, bufsizenm, &pwptr)) != 0) {
if (pwd_not_found(enm)) {
if (enm == ENOENT || enm== ESRCH || enm == EBADF || enm == EPERM) {
/* not found; non-errors */
rb_str_resize(getpwnm_tmp, 0); rb_str_resize(getpwnm_tmp, 0);
return Qnil; return Qnil;
} }
@ -5837,21 +5856,21 @@ rb_getpwdirnam_for_login(VALUE login_name)
rb_str_resize(getpwnm_tmp, 0); rb_str_resize(getpwnm_tmp, 0);
return result; return result;
# elif USE_GETPWNAM # elif defined(USE_GETPWNAM)
errno = 0; errno = 0;
pwptr = getpwnam(login); if (!(pwptr = getpwnam(login))) {
if (pwptr) { int err = errno;
/* found it */
return rb_str_new_cstr(pwptr->pw_dir); if (pwd_not_found(err)) {
} return Qnil;
if (errno }
/* avoid treating as errors errno values that indicate "not found" */
&& ( errno != ENOENT && errno != ESRCH && errno != EBADF && errno != EPERM)) { rb_syserr_fail(err, "getpwnam");
rb_syserr_fail(errno, "getpwnam");
} }
return Qnil; /* not found */ /* found it */
return rb_str_new_cstr(pwptr->pw_dir);
# endif # endif
#endif #endif
@ -5887,11 +5906,8 @@ rb_getpwdiruid(void)
rb_str_set_len(getpwid_tmp, bufsizeid); rb_str_set_len(getpwid_tmp, bufsizeid);
int eid; int eid;
errno = 0;
while ((eid = getpwuid_r(ruid, &pwdid, bufid, bufsizeid, &pwptr)) != 0) { while ((eid = getpwuid_r(ruid, &pwdid, bufid, bufsizeid, &pwptr)) != 0) {
if (pwd_not_found(eid)) {
if (eid == ENOENT || eid== ESRCH || eid == EBADF || eid == EPERM) {
/* not found; non-errors */
rb_str_resize(getpwid_tmp, 0); rb_str_resize(getpwid_tmp, 0);
return Qnil; return Qnil;
} }
@ -5920,18 +5936,18 @@ rb_getpwdiruid(void)
# elif defined(USE_GETPWUID) # elif defined(USE_GETPWUID)
errno = 0; errno = 0;
pwptr = getpwuid(ruid); if (!(pwptr = getpwuid(ruid))) {
if (pwptr) { int err = errno;
/* found it */
return rb_str_new_cstr(pwptr->pw_dir); if (pwd_not_found(err)) {
} return Qnil;
if (errno }
/* avoid treating as errors errno values that indicate "not found" */
&& ( errno == ENOENT || errno == ESRCH || errno == EBADF || errno == EPERM)) { rb_syserr_fail(err, "getpwuid");
rb_syserr_fail(errno, "getpwuid");
} }
return Qnil; /* not found */ /* found it */
return rb_str_new_cstr(pwptr->pw_dir);
# endif # endif
#endif /* !defined(USE_GETPWUID_R) && !defined(USE_GETPWUID) */ #endif /* !defined(USE_GETPWUID_R) && !defined(USE_GETPWUID) */