[Xfce4-commits] <libxfce4util:master> Expand tilde in more situations in xfce_expand_variables().

Nick Schermer noreply at xfce.org
Wed Oct 27 20:48:01 CEST 2010


Updating branch refs/heads/master
         to 3f4e4e0188d409fb31f52c9723eb412b652b398e (commit)
       from e0d6fc59bf734fcac294982992680286f2594387 (commit)

commit 3f4e4e0188d409fb31f52c9723eb412b652b398e
Author: Nick Schermer <nick at xfce.org>
Date:   Wed Oct 27 20:40:48 2010 +0200

    Expand tilde in more situations in xfce_expand_variables().
    
    Also allow to expand ~ and ~user in the following cases instead of
    only at the start of the command:
    ~ is after a space, a = sign or quoted (start with ' or "). This
    allows to expand command line "thunar ~/music",
    "terminal --working-directory=~/scripts" or "thunar '~/my music'".
    
    Also drop the static buffers and use a GString to build the function
    result.
    
    Also fix a bug where underscores were no usable in expanding variables.

 libxfce4util/xfce-miscutils.c |  171 +++++++++++++++++++++++------------------
 1 files changed, 95 insertions(+), 76 deletions(-)

diff --git a/libxfce4util/xfce-miscutils.c b/libxfce4util/xfce-miscutils.c
index 56db56e..fd9bec8 100644
--- a/libxfce4util/xfce-miscutils.c
+++ b/libxfce4util/xfce-miscutils.c
@@ -62,7 +62,6 @@
 #include <libxfce4util/libxfce4util.h>
 #include <libxfce4util/libxfce4util-alias.h>
 
-
 #define XFCE4DIR		".xfce4"
 
 /* environment variable the user can set to change the path to
@@ -496,118 +495,138 @@ xfce_unsetenv (const gchar *name)
 
 
 
+static inline gboolean
+xfce_is_valid_tilde_prefix (const gchar *p)
+{
+  if (g_ascii_isspace (*p) /* thunar ~/music */
+      || *p == '=' /* terminal --working-directory=~/ */
+      || *p == '\'' || *p == '"') /* terminal --working-directory '~my music' */
+    return TRUE;
+
+  return FALSE;
+}
+
+
+
 /**
  * xfce_expand_variables:
- * @command : Input string.
+ * @command : Input string or %NULL.
  * @envp    : Addition environment variables to take into account. These
  *            variables have higher priority than the ones in the process's
  *            environment.
  *
  * Expands shell like environment variables and tilde (~/ and ~user/ are both supported)
- * in @command. 
+ * in @command.
  *
  * Return value: %NULL on error, else the string, which should be freed using
  *               g_free() when no longer needed.
  *
  * Since: 4.2
  **/
-gchar*
+gchar *
 xfce_expand_variables (const gchar *command,
                        gchar      **envp)
 {
+  GString        *buf;
+  const gchar    *start;
+  gchar          *variable;
+  const gchar    *p;
+  const gchar    *value;
+  gchar         **ep;
+  guint           len;
 #ifdef HAVE_GETPWNAM
-  struct passwd *pw;
+  struct passwd  *pw;
+  gchar          *username;
 #endif
-  const gchar   *value;
-  gchar          variable[256];
-  gchar          buffer[2048];
-  gchar         *bend = buffer + 2047;
-  gchar         *bp = buffer;
-  gchar         *vend = variable + 255;
-  gchar         *vp;
-  gchar        **ep;
-  guint          len;
-
-  g_return_val_if_fail (command != NULL, NULL);
-  
-  if (*command == '~')
+
+  if (G_UNLIKELY (command == NULL))
+    return NULL;
+
+  buf = g_string_sized_new (strlen (command));
+
+  for (p = command; *p != '\0'; ++p)
     {
-      if (*++command == '/' || *command == '\0')
-        {
-          /* ~/ syntax */
-          g_strlcpy (buffer, xfce_get_homedir (), 2048);
-          bp = buffer + strlen (buffer);
-        }
-#ifdef HAVE_GETPWNAM
-      else
+      if (*p == '~'
+          && (p == command
+              || xfce_is_valid_tilde_prefix (p - 1)))
         {
-          /* ~user/ syntax */
-          for (vp = variable; g_ascii_isalnum (*command) && vp < vend; )
-            *vp++ = *command++;
+          /* walk to the end of the string or to a directory separator */
+          for (start = ++p; *p != '\0' && *p != G_DIR_SEPARATOR; ++p);
 
-          if (vp != variable)
+          if (G_LIKELY (start == p))
             {
-              *vp = '\0';
+              /* add the current user directory */
+              buf = g_string_append (buf, xfce_get_homedir ());
+            }
+          else
+            {
+#ifdef HAVE_GETPWNAM
+              username = g_strndup (start, p - start);
+              pw = getpwnam (username);
+              g_free (username);
 
-              pw = getpwnam (variable);
+              /* add the users' home directory if found, fallback to the
+               * not-expanded string */
               if (pw != NULL && pw->pw_dir != NULL)
-                {
-                  g_strlcpy (buffer, pw->pw_dir, 2048);
-                  bp = buffer + strlen (buffer);
-                }
+                buf = g_string_append (buf, pw->pw_dir);
+              else
+#endif
+                buf = g_string_append_len (buf, start - 1, p - start + 1);
             }
         }
-#endif
-    }
-  
-  while (*command != '\0' && bp < bend)
-    {
-      if (*command != '$')
-        *bp++ = *command++;
-      else
+      else if (*p == '$')
         {
-          ++command;
-          
-          for (vp = variable; g_ascii_isalnum (*command) && vp < vend; )
-            *vp++ = *command++;
+          /* walk to the end of a valid variable name */
+          for (start = ++p; *p != '\0' && (g_ascii_isalnum (*p) || *p == '_'); ++p);
           
-          if (vp == variable)
-            continue;
-
-          *vp = '\0';
-          len = vp - variable;
-          value = NULL;
-          
-          if (envp != NULL)
+          if (start < p)
             {
-              for (ep = envp; *ep != NULL; ++ep)
-                if (strncmp (*ep, variable, len) == 0 && (*ep)[len] == '=')
-                  {
-                    value = (*ep) + len + 1;
-                    break;
-                  }
-            }
-          
-          if (value == NULL)
-            value = g_getenv (variable);
+              value = NULL;
+              len = p - start;
 
-          if (value != NULL)
-            {
-              while (*value != '\0' && bp < bend)
-                *bp++ = *value++;
+              /* lookup the variable in the environment supplied by the user */
+              if (envp != NULL)
+                {
+                  /* format is NAME=VALUE */
+                  for (ep = envp; *ep != NULL; ++ep)
+                    if (strncmp (*ep, start, len) == 0
+                        && (*ep)[len] == '=')
+                      {
+                        value = (*ep) + len + 1;
+                        break;
+                      }
+                }
+
+              /* fallback to the environment */
+              if (value == NULL)
+                {
+                  variable = g_strndup (start, len);
+                  value = g_getenv (variable);
+                  g_free (variable);
+                }
+
+              if (G_LIKELY (value != NULL))
+                {
+                  buf = g_string_append (buf, value);
+                }
+              else
+                {
+                  /* unable the parse the string, reset and continue
+                   * adding the characters */
+                  p = start - 1;
+                }
             }
           else
             {
-              *bp++ = '$';
-              for (vp = variable; *vp != '\0' && bp < bend; )
-                *bp++ = *vp++;
+              /* add the $ character and continue */
+              --p;
             }
         }
-    }
 
-  *bp = '\0';
+      buf = g_string_append_c (buf, *p);
+    }
 
-  return g_strdup (buffer);
+  return g_string_free (buf, FALSE);
 }
 
 



More information about the Xfce4-commits mailing list