From 08e142b209a4919aac527bb0ce174a0ca0333d5c Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Wed, 4 Sep 2024 11:44:12 +0900 Subject: [PATCH] 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` --- process.c | 102 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 59 insertions(+), 43 deletions(-) diff --git a/process.c b/process.c index 09b0cc8d17..acb5b66156 100644 --- a/process.c +++ b/process.c @@ -5700,6 +5700,12 @@ check_gid_switch(void) #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, * associated with the process. Processes not descended from login(1) (or @@ -5708,18 +5714,18 @@ check_gid_switch(void) VALUE rb_getlogin(void) { -#if ( !defined(USE_GETLOGIN_R) && !defined(USE_GETLOGIN) ) +# if !defined(USE_GETLOGIN_R) && !defined(USE_GETLOGIN) return Qnil; -#else +# else char MAYBE_UNUSED(*login) = NULL; # ifdef USE_GETLOGIN_R -#if defined(__FreeBSD__) +# if defined(__FreeBSD__) typedef int getlogin_r_size_t; -#else +# else typedef size_t getlogin_r_size_t; -#endif +# endif long loginsize = GETLOGIN_R_SIZE_INIT; /* maybe -1 */ @@ -5733,10 +5739,8 @@ rb_getlogin(void) rb_str_set_len(maybe_result, loginsize); int gle; - errno = 0; while ((gle = getlogin_r(login, (getlogin_r_size_t)loginsize)) != 0) { - - if (gle == ENOTTY || gle == ENXIO || gle == ENOENT) { + if (login_not_found(gle)) { rb_str_resize(maybe_result, 0); return Qnil; } @@ -5756,17 +5760,19 @@ rb_getlogin(void) return Qnil; } + rb_str_set_len(maybe_result, strlen(login)); return maybe_result; -# elif USE_GETLOGIN +# elif defined(USE_GETLOGIN) errno = 0; login = getlogin(); - if (errno) { - if (errno == ENOTTY || errno == ENXIO || errno == ENOENT) { + int err = errno; + if (err) { + if (login_not_found(err)) { return Qnil; } - rb_syserr_fail(errno, "getlogin"); + rb_syserr_fail(err, "getlogin"); } return login ? rb_str_new_cstr(login) : Qnil; @@ -5775,10 +5781,26 @@ rb_getlogin(void) #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 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; #else @@ -5787,7 +5809,7 @@ rb_getpwdirnam_for_login(VALUE login_name) return Qnil; } - char *login = RSTRING_PTR(login_name); + const char *login = RSTRING_PTR(login_name); struct passwd *pwptr; @@ -5807,11 +5829,8 @@ rb_getpwdirnam_for_login(VALUE login_name) rb_str_set_len(getpwnm_tmp, bufsizenm); int enm; - errno = 0; while ((enm = getpwnam_r(login, &pwdnm, bufnm, bufsizenm, &pwptr)) != 0) { - - if (enm == ENOENT || enm== ESRCH || enm == EBADF || enm == EPERM) { - /* not found; non-errors */ + if (pwd_not_found(enm)) { rb_str_resize(getpwnm_tmp, 0); return Qnil; } @@ -5837,21 +5856,21 @@ rb_getpwdirnam_for_login(VALUE login_name) rb_str_resize(getpwnm_tmp, 0); return result; -# elif USE_GETPWNAM +# elif defined(USE_GETPWNAM) errno = 0; - pwptr = getpwnam(login); - if (pwptr) { - /* found it */ - return rb_str_new_cstr(pwptr->pw_dir); - } - if (errno - /* avoid treating as errors errno values that indicate "not found" */ - && ( errno != ENOENT && errno != ESRCH && errno != EBADF && errno != EPERM)) { - rb_syserr_fail(errno, "getpwnam"); + if (!(pwptr = getpwnam(login))) { + int err = errno; + + if (pwd_not_found(err)) { + return Qnil; + } + + rb_syserr_fail(err, "getpwnam"); } - return Qnil; /* not found */ + /* found it */ + return rb_str_new_cstr(pwptr->pw_dir); # endif #endif @@ -5887,11 +5906,8 @@ rb_getpwdiruid(void) rb_str_set_len(getpwid_tmp, bufsizeid); int eid; - errno = 0; while ((eid = getpwuid_r(ruid, &pwdid, bufid, bufsizeid, &pwptr)) != 0) { - - if (eid == ENOENT || eid== ESRCH || eid == EBADF || eid == EPERM) { - /* not found; non-errors */ + if (pwd_not_found(eid)) { rb_str_resize(getpwid_tmp, 0); return Qnil; } @@ -5920,18 +5936,18 @@ rb_getpwdiruid(void) # elif defined(USE_GETPWUID) errno = 0; - pwptr = getpwuid(ruid); - if (pwptr) { - /* found it */ - return rb_str_new_cstr(pwptr->pw_dir); - } - if (errno - /* avoid treating as errors errno values that indicate "not found" */ - && ( errno == ENOENT || errno == ESRCH || errno == EBADF || errno == EPERM)) { - rb_syserr_fail(errno, "getpwuid"); + if (!(pwptr = getpwuid(ruid))) { + int err = errno; + + if (pwd_not_found(err)) { + return Qnil; + } + + rb_syserr_fail(err, "getpwuid"); } - return Qnil; /* not found */ + /* found it */ + return rb_str_new_cstr(pwptr->pw_dir); # endif #endif /* !defined(USE_GETPWUID_R) && !defined(USE_GETPWUID) */