[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