summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2015-06-18 11:57:12 +0200
committerAlexander Larsson <alexl@redhat.com>2015-06-22 17:29:19 +0200
commit6e26045943d27656b4444e157d0d10c025aa69db (patch)
treec95ff4fd1b4c4f4e3a24420a53cebc34678ad225 /common
parent60058fd5bdf289fe9210671447aaf027c8cd8a03 (diff)
downloadgdm-6e26045943d27656b4444e157d0d10c025aa69db.tar.gz
gdm-common: Add gdm_shell_expand() and tests
This allows shell-like expansion of strings. It will be later used to allow configuring the environment via config files. https://bugzilla.gnome.org/show_bug.cgi?id=751158
Diffstat (limited to 'common')
-rw-r--r--common/gdm-common.c87
-rw-r--r--common/gdm-common.h9
2 files changed, 96 insertions, 0 deletions
diff --git a/common/gdm-common.c b/common/gdm-common.c
index 5beeebf9..a96b30f2 100644
--- a/common/gdm-common.c
+++ b/common/gdm-common.c
@@ -710,3 +710,90 @@ gdm_run_script (const char *dir,
return ret;
}
+
+gboolean
+gdm_shell_var_is_valid_char (gchar c, gboolean first)
+{
+ return (!first && g_ascii_isdigit (c)) ||
+ c == '_' ||
+ g_ascii_isalpha (c);
+}
+
+/* This expands a string somewhat similar to how a shell would do it
+ if it was enclosed inside double quotes. It handles variable
+ expansion like $FOO and ${FOO}, single-char escapes using \, and
+ non-escaped # at the begining of a word is taken as a comment and ignored */
+char *
+gdm_shell_expand (const char *str,
+ GdmExpandVarFunc expand_var_func,
+ gpointer user_data)
+{
+ GString *s = g_string_new("");
+ const gchar *p, *start;
+ gchar c;
+ gboolean at_new_word;
+
+ p = str;
+ at_new_word = TRUE;
+ while (*p) {
+ c = *p;
+ if (c == '\\') {
+ p++;
+ c = *p;
+ if (c != '\0') {
+ p++;
+ switch (c) {
+ case '\\':
+ g_string_append_c (s, '\\');
+ break;
+ case '$':
+ g_string_append_c (s, '$');
+ break;
+ case '#':
+ g_string_append_c (s, '#');
+ break;
+ default:
+ g_string_append_c (s, '\\');
+ g_string_append_c (s, c);
+ break;
+ }
+ }
+ } else if (c == '#' && at_new_word) {
+ break;
+ } else if (c == '$') {
+ gboolean brackets = FALSE;
+ p++;
+ if (*p == '{') {
+ brackets = TRUE;
+ p++;
+ }
+ start = p;
+ while (*p != '\0' &&
+ gdm_shell_var_is_valid_char (*p, p == start))
+ p++;
+ if (p == start || (brackets && *p != '}')) {
+ /* Invalid variable, use as-is */
+ g_string_append_c (s, '$');
+ if (brackets)
+ g_string_append_c (s, '{');
+ g_string_append_len (s, start, p - start);
+ } else {
+ gchar *expanded;
+ gchar *var = g_strndup (start, p - start);
+ if (brackets && *p == '}')
+ p++;
+
+ expanded = expand_var_func (var, user_data);
+ if (expanded)
+ g_string_append (s, expanded);
+ g_free (var);
+ g_free (expanded);
+ }
+ } else {
+ p++;
+ g_string_append_c (s, c);
+ at_new_word = g_ascii_isspace (c);
+ }
+ }
+ return g_string_free (s, FALSE);
+}
diff --git a/common/gdm-common.h b/common/gdm-common.h
index 3302afec..d0812ed3 100644
--- a/common/gdm-common.h
+++ b/common/gdm-common.h
@@ -36,6 +36,9 @@
GQuark gdm_common_error_quark (void);
#define GDM_COMMON_ERROR gdm_common_error_quark()
+typedef char * (*GdmExpandVarFunc) (const char *var,
+ gpointer user_data);
+
G_BEGIN_DECLS
int gdm_wait_on_pid (int pid);
@@ -64,6 +67,12 @@ gboolean gdm_run_script (const char *dir,
const char *display_hostname,
const char *display_x11_authority_file);
+gboolean gdm_shell_var_is_valid_char (char c,
+ gboolean first);
+char * gdm_shell_expand (const char *str,
+ GdmExpandVarFunc expand_func,
+ gpointer user_data);
+
G_END_DECLS
#endif /* _GDM_COMMON_H */