#include "gshell.h"
#include "gslist.h"
+#include "gstrfuncs.h"
#include "gstring.h"
#include "gtestutils.h"
#include "glibintl.h"
+#include "gthread.h"
/**
- * SECTION: shell
+ * SECTION:shell
* @title: Shell-related Utilities
* @short_description: shell-like commandline handling
- **/
+ *
+ * GLib provides the functions g_shell_quote() and g_shell_unquote()
+ * to handle shell-like quoting in strings. The function g_shell_parse_argv()
+ * parses a string similar to the way a POSIX shell (/bin/sh) would.
+ *
+ * Note that string handling in shells has many obscure and historical
+ * corner-cases which these functions do not necessarily reproduce. They
+ * are good enough in practice, though.
+ */
/**
* G_SHELL_ERROR:
*
* Error codes returned by shell functions.
**/
-GQuark
-g_shell_error_quark (void)
-{
- return g_quark_from_static_string ("g-shell-error-quark");
-}
+G_DEFINE_QUARK (g-shell-error-quark, g_shell_error)
/* Single quotes preserve the literal string exactly. escape
* sequences are not allowed; not even \' - if you want a '
* quoting style used is undefined (single or double quotes may be
* used).
*
- * Return value: quoted string
+ * Returns: quoted string
**/
gchar*
g_shell_quote (const gchar *unquoted_string)
* be escaped with backslash. Otherwise double quotes preserve things
* literally.
*
- * Return value: an unquoted string
+ * Returns: an unquoted string
**/
gchar*
g_shell_unquote (const gchar *quoted_string,
g_string_append_c (current_token, *p);
/* FALL THRU */
-
- case '#':
case '\\':
current_quote = *p;
break;
+ case '#':
+ if (p == command_line)
+ { /* '#' was the first char */
+ current_quote = *p;
+ break;
+ }
+ switch(*(p-1))
+ {
+ case ' ':
+ case '\n':
+ case '\0':
+ current_quote = *p;
+ break;
+ default:
+ ensure_token (¤t_token);
+ g_string_append_c (current_token, *p);
+ break;
+ }
+ break;
+
default:
/* Combines rules 4) and 6) - if we have a token, append to it,
* otherwise create a new token.
error:
g_assert (error == NULL || *error != NULL);
-
- if (retval)
- {
- g_slist_foreach (retval, (GFunc)g_free, NULL);
- g_slist_free (retval);
- }
+
+ g_slist_free_full (retval, g_free);
return NULL;
}
/**
* g_shell_parse_argv:
* @command_line: command line to parse
- * @argcp: return location for number of args
- * @argvp: return location for array of args
- * @error: return location for error
+ * @argcp: (out) (optional): return location for number of args, or %NULL
+ * @argvp: (out) (optional) (array length=argcp zero-terminated=1): return
+ * location for array of args, or %NULL
+ * @error: (optional): return location for error, or %NULL
*
* Parses a command line into an argument vector, in much the same way
* the shell would, but without many of the expansions the shell would
* literally. Possible errors are those from the #G_SHELL_ERROR
* domain. Free the returned vector with g_strfreev().
*
- * Return value: %TRUE on success, %FALSE if error set
+ * Returns: %TRUE on success, %FALSE if error set
**/
gboolean
g_shell_parse_argv (const gchar *command_line,
++i;
}
- g_slist_foreach (tokens, (GFunc)g_free, NULL);
- g_slist_free (tokens);
+ g_slist_free_full (tokens, g_free);
if (argcp)
*argcp = argc;
g_assert (error == NULL || *error != NULL);
g_strfreev (argv);
- g_slist_foreach (tokens, (GFunc) g_free, NULL);
- g_slist_free (tokens);
+ g_slist_free_full (tokens, g_free);
return FALSE;
}