diff options
Diffstat (limited to 'src/shared')
-rw-r--r-- | src/shared/util.c | 51 | ||||
-rw-r--r-- | src/shared/util.h | 1 |
2 files changed, 50 insertions, 2 deletions
diff --git a/src/shared/util.c b/src/shared/util.c index b5ffaa1c3c..20aec2a5c9 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -5220,10 +5220,10 @@ int make_console_stdio(void) { } int get_home_dir(char **_h) { - char *h; + struct passwd *p; const char *e; + char *h; uid_t u; - struct passwd *p; assert(_h); @@ -5266,6 +5266,53 @@ int get_home_dir(char **_h) { return 0; } +int get_shell(char **_s) { + struct passwd *p; + const char *e; + char *s; + uid_t u; + + assert(_s); + + /* Take the user specified one */ + e = getenv("SHELL"); + if (e) { + s = strdup(e); + if (!s) + return -ENOMEM; + + *_s = s; + return 0; + } + + /* Hardcode home directory for root to avoid NSS */ + u = getuid(); + if (u == 0) { + s = strdup("/bin/sh"); + if (!s) + return -ENOMEM; + + *_s = s; + return 0; + } + + /* Check the database... */ + errno = 0; + p = getpwuid(u); + if (!p) + return errno > 0 ? -errno : -ESRCH; + + if (!path_is_absolute(p->pw_shell)) + return -EINVAL; + + s = strdup(p->pw_shell); + if (!s) + return -ENOMEM; + + *_s = s; + return 0; +} + bool filename_is_safe(const char *p) { if (isempty(p)) diff --git a/src/shared/util.h b/src/shared/util.h index d5fa81c6a5..6fc77808d4 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -552,6 +552,7 @@ bool in_initrd(void); void warn_melody(void); int get_home_dir(char **ret); +int get_shell(char **_ret); static inline void freep(void *p) { free(*(void**) p); |