diff options
author | Werner Fink | 2010-08-17 09:09:55 +0200 |
---|---|---|
committer | Ludwig Nussel | 2012-05-24 13:52:43 +0200 |
commit | a6fdd3f8125be23930d955c2bc6b7a46cdaf8a12 (patch) | |
tree | cce6fa51cbe507325751ee516522cc7f15bd99c8 /login-utils/su.c | |
parent | honor settings in /etc/default/su resp /etc/login.defs (diff) | |
download | kernel-qcow2-util-linux-a6fdd3f8125be23930d955c2bc6b7a46cdaf8a12.tar.gz kernel-qcow2-util-linux-a6fdd3f8125be23930d955c2bc6b7a46cdaf8a12.tar.xz kernel-qcow2-util-linux-a6fdd3f8125be23930d955c2bc6b7a46cdaf8a12.zip |
make sure /sbin resp /usr/sbin are in PATH
Diffstat (limited to 'login-utils/su.c')
-rw-r--r-- | login-utils/su.c | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/login-utils/su.c b/login-utils/su.c index 69043f695..c2311d5a6 100644 --- a/login-utils/su.c +++ b/login-utils/su.c @@ -471,6 +471,117 @@ correct_password (const struct passwd *pw) #endif /* !USE_PAM */ } +/* Add or clear /sbin and /usr/sbin for the su command + used without `-'. */ + +/* Set if /sbin is found in path. */ +#define SBIN_MASK 0x01 +/* Set if /usr/sbin is found in path. */ +#define USBIN_MASK 0x02 + +static char * +addsbin (const char *const path) +{ + unsigned char smask = 0; + char *ptr, *tmp, *cur, *ret = NULL; + size_t len; + + if (!path || *path == 0) + return NULL; + + tmp = xstrdup (path); + cur = tmp; + for (ptr = strsep (&cur, ":"); ptr != NULL; ptr = strsep (&cur, ":")) + { + if (!strcmp (ptr, "/sbin")) + smask |= SBIN_MASK; + if (!strcmp (ptr, "/usr/sbin")) + smask |= USBIN_MASK; + } + + if ((smask & (USBIN_MASK|SBIN_MASK)) == (USBIN_MASK|SBIN_MASK)) + { + free (tmp); + return NULL; + } + + len = strlen (path); + if (!(smask & USBIN_MASK)) + len += strlen ("/usr/sbin:"); + + if (!(smask & SBIN_MASK)) + len += strlen (":/sbin"); + + ret = xmalloc (len + 1); + strcpy (tmp, path); + + *ret = 0; + cur = tmp; + for (ptr = strsep (&cur, ":"); ptr; ptr = strsep (&cur, ":")) + { + if (!strcmp (ptr, ".")) + continue; + if (*ret) + strcat (ret, ":"); + if (!(smask & USBIN_MASK) && !strcmp (ptr, "/bin")) + { + strcat (ret, "/usr/sbin:"); + strcat (ret, ptr); + smask |= USBIN_MASK; + continue; + } + if (!(smask & SBIN_MASK) && !strcmp (ptr, "/usr/bin")) + { + strcat (ret, ptr); + strcat (ret, ":/sbin"); + smask |= SBIN_MASK; + continue; + } + strcat (ret, ptr); + } + free (tmp); + + if (!(smask & USBIN_MASK)) + strcat (ret, ":/usr/sbin"); + + if (!(smask & SBIN_MASK)) + strcat (ret, ":/sbin"); + + return ret; +} + +static char * +clearsbin (const char *const path) +{ + char *ptr, *tmp, *cur, *ret = NULL; + + if (!path || *path == 0) + return NULL; + + tmp = strdup (path); + if (!tmp) + return NULL; + + ret = xmalloc (strlen (path) + 1); + *ret = 0; + cur = tmp; + for (ptr = strsep (&cur, ":"); ptr; ptr = strsep (&cur, ":")) + { + if (!strcmp (ptr, "/sbin")) + continue; + if (!strcmp (ptr, "/usr/sbin")) + continue; + if (!strcmp (ptr, "/usr/local/sbin")) + continue; + if (*ret) + strcat (ret, ":"); + strcat (ret, ptr); + } + free (tmp); + + return ret; +} + /* Update `environ' for the new shell based on PW, with SHELL being the value for the SHELL environment variable. */ @@ -510,6 +621,22 @@ modify_environment (const struct passwd *pw, const char *shell) DEFAULT_LOGIN_PATH) : getdef_str ("SUPATH", DEFAULT_ROOT_LOGIN_PATH))); + else + { + char const *path = getenv ("PATH"); + char *new = NULL; + + if (pw->pw_uid) + new = clearsbin (path); + else + new = addsbin (path); + + if (new) + { + xsetenv ("PATH", new); + free (new); + } + } if (pw->pw_uid) { xsetenv ("USER", pw->pw_name); |