LogoopenSUSE Build Service > Projects
Sign Up | Log In

View File make-sure-sbin-resp-usr-sbin-are-in-PATH.diff of Package util-linux (Project Base:System)

--- util-linux-2.23.1/login-utils/su-common.c
+++ util-linux-2.23.1/login-utils/su-common.c	2013-06-06 08:46:59.575872090 +0000
@@ -473,6 +473,117 @@ set_path(const struct passwd* pw)
     err (EXIT_FAILURE,  _("failed to set PATH"));
 }
 
+/* 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.  */
 
@@ -508,6 +619,22 @@ modify_environment (const struct passwd
             xsetenv ("SHELL", shell, 1);
 	  if (getlogindefs_bool ("ALWAYS_SET_PATH", 0))
 	    set_path(pw);
+	  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, 1);
+		  free (new);
+		}
+	    }
 
           if (pw->pw_uid)
             {